عند النظر للمرة الأولى لبعض الصيغ البرمجية المكتوبة بروبي ، علىالأغلب ستقوم بتذكيرك بلغات البرمجة الأخرى التي قمت باستعمالها.و هذا الأمر عن عمد. الكثير من الصيغ البرمجية ستكون مفهومة لمبرمجي بايثون ، بيرل و جافا ( على الأخص ) ، لذلك إذا ما استخدمت احد هذه اللغات ، فتعلم روبي سيكون سهلاً جداً.
هذا الملف يحتوي على قسمين رئيسين . الأول يهدف إلى تلخيص ما ستتعرض له عند الانتقال من اللغة X إلى روبي . الجزء الثاني يتناول الميزات الرئيسية للغة ، و كيفية مقارنتها مع ما انت متآلف معه من لغات .
ماذا يجب ان تتوقع : الانتقال من اللغة X إلى روبي
- إلى روبي من بايثون
- إلى روبي من جافا
- إلي روبي من بي أتش بي
- إلي روبي من بيرل
- إلي روبي من سي وسي بلس بلس
ميزات اللغة المهمة و بعض المعلومات
هذه بعض النقاط و التلميحات على ميزات روبي الأساسية التي ستقرأ عنها بينما تقوم بتعلم اللغة .
التكرار (Iteration)
ميزتين في روبي قتم بناؤهما بطريقة تختلف عن اي طريقة قرأت عنها من قبل ، و التي قد تأخذ بعض الوقت لتعتاد عليهما ، و هاتين الميزتين هما الـ blocks و التكرار iterators . بدلاً من اجراء عملية التكرار بالاعتماد على الفهرس ( index ) – كما في اللغات مثل C, C++, or pre-1.5 Java – أو التكرار في القائمة – كما في Perl’s for (@a) {...}, or Python’s for i in aList: ... – مع روبي عوضاً عن ذلك ستشاهد :
some_list.each do |this_item|
# We're inside the block.
# deal with this_item.
end
لمزيد من المعلومات عن each ( و اصدقائها collect, find, inject, sort و غيرهم )
راجع ri Enumerable ( و بعد ذلك ri Enumerable#func_name )
كل شيء له قيمة
لا يوجد اي فرق بين التعبير و البيان . كل شيء له قيمة حتى و ان كانت هذه القيمة هي nil. و هذا ممكن :
x = 10
y = 11
z = if x < y
true
else
false
end
z # => true
الرموز ليست أحرف خفيفة
العديد من مبرمجي روبي المبتدئين يعانون من مشكلة فهم الرموز ، و ما الذي ستستخدم لأجله.
أفضل وصف للرموز بأنها هويات . المهم في الرمز من هي و ليس ماهيتها.
قم بتشغيل irb و شاهد الاختلافات :
irb(main):001:0> :george.object_id == :george.object_id
=> true
irb(main):002:0> "george".object_id == "george".object_id
=> false
irb(main):003:0>
إن الاجرائية object_id تقوم بارجاع هوية العنصر. في حال لدينا عنصرين لهما نفس
object_id, فهما متشابهين (يقومان بالاشارة إلى نفس العنصر في الذاكرة).
كما تلاحظ ، فعندما تقوم باستخدام رمز ، فإن اي رمز بنفس الأحرف سيشير إلى نفس العنصر في الذاكرة.
و بالتالي فإن اي رمزين لهما نفس الأحرف ، فإن الـ object_id الخاص بهما يتطابق.
الآن انظر إلى سلسلة المحارف (“george”). إن object_id لا يتطابق.
و هذا يعني انهما يشيران إلى عنصرين مختلفين في الذاكرة.
عندما تقوم باستخدام سلسلة محارف جديدة ،تقوم روبي بحجز الذاكرة لها.
إن كنت في حالة حيرة فيما إذا كنت تريد استخدام الرموز ام سلسلة المحارف ، عليك بتحديد ماهو المهم : هوية العنصر (i.e. a Hash key), ام المحتوى ( في المثال السابق المحتوى هو , “george”).
كل شيء عبارة عن عنصر
“كل شيء عبارة عن عنصر” ليست مبالغة . حتى الأصناف و الأرقام هي عناصر , و يمكنك التعامل معهما كما تتعامل مع اي عنصر آخر:
# This is the same as
# class MyClass
# attr_accessor :instance_var
# end
MyClass = Class.new do
attr_accessor :instance_var
end
المتحولات الثابتة
الثوابت ليست ثابتة بالفعل . فلو قمت بالتعديل على ثابت معرف مسبقاُ، فهذا الأمر سيقوم باطلاق تحذير ، و لكنه لن يقوم بايقاف برنامجك . و هذا لا يعني أنه يجب اعادة تعريف الثوابت .
قواعد التسمية
روبي تفرض بعض قواعد التسمية . إذا بدء المعرّف بحرف كبير هو معرّف ثابت.
إذا ما ابتدأ باشارة الدولار ($), فهو متحول عام.
إذا ما ابتدأ بـ @, فهو متحول آني . إذا ما ابتدأ بـ @@,
فهو متحول خاص بالصنف.
اسماء الاجرائيات ، بغض النظر ، من الممكن ان تبدأ باحرف كبيرة . و هذا الأمر قد يسبب لارتباك كما في المثال التالي :
Constant = 10
def Constant
11
end
الآن إن قيمة Constant هي 10, لكن قيمة Constant() هي 11.
الباراميتر الزائف
روبي لا تمتلك باراميترات و كما تمتلك بايثون. على كل من الممكن تزييف الباراميترات ياستخدام الرموز و الـ hashes.
(Ruby doesn’t have keyword parameters, like Python has. However, it can be faked by using symbols and hashes ).
ريلز ، بالأخص ، تستخدم هذا الموضوع بكثافة ، مثال :
def some_keyword_params( params )
params
end
some_keyword_params( :param_one => 10, :param_two => 42 )
# => {:param_one=>10, :param_two=>42}
الحقيقة العالمية
في روبي كل شيء ماعدا nil و false يعتبر حقيقي ( true ). في لغات البرمجة كـ C , Python و العديد من اللغات , 0 و ربما قيم أخرى , كاللوائح الفارغة , تعتبر غير حقيقية false. قم بالاطلاع على النص البرمجي التالي و المكتوب بلغة Python ( المثال ينطبق ايضاً على لغات برمجية اخرى):
# in Python
if 0:
print "0 is true"
else:
print "0 is false"
و النتيجة ستكون “0 is false”. و المقابل في روبي:
# in Ruby
if 0
puts "0 is true"
else
puts "0 is false"
end
و الذي سيطبع “0 is true”.
حق الوصول للاجرائيات يطبق حتى نهاية المدى
في النص البرمجي لروبي نجد :
class MyClass
private
def a_method; true; end
def another_method; false; end
end
قد تظن بأن another_method ستكون عامة . لكنك مخطئ. إن كلمة ‘private’ لحق الوصول للاجرائيات ستطبق حتى نهاية المدى , أو حتى كتابة او تعريف حق للوصول ، ايهما يحدث قبل الآخر . بشكل افتراضي الاجائيات عامة:
class MyClass
# Now a_method is public
def a_method; true; end
private
# another_method is private
def another_method; false; end
end
public, private و protected هي بالحقيقة اجرائيات ,
لذلك من الممكن ان تأخذ باراميترات . إذا ما قمت بتمرير رمز لأحدها ، فإنه يتم التعديل على مستوى الظهور ( visibility ) الخاص بتلك الاجرائية.
حق الوصول للاجرائية
في لغة جافا , public تعني بأن حق الوصول لهذه الاجرائية مفتوح للجميع . protected
تعني بأن المتحول الخاص بالصنف , المتحول الخاص بأبناء هذا الصنف , و متحولات الأصناف التي من نفس المجموعة تستطيع الوصول إليه ، و لا أحد غيرهم
, و private لا أحد يستطيع الوصول للاجرائية بحانب المتحولات الخاصة بالصنف .
تختلف روبي بشكل بسيط .public هو بطبيعة الحال عام. private تعني بأنه من الممكن الوصول للاجرائية / الاجرائيات فقط عندما يمكن استدعائها دون وجود مستقبل صريح . فقط self مسموح له بأن يكون مستقبل لاستدعاء الاجرائية الخاصة ( private method ) .
protected هي التي يجب الانتباه لها. الاجرائية المحمية هي التي من الممكن استدعائها من الصنف أو من متحولات الأصناف الأبناء ، لكن مع وجود متحول كمستقبل له.
مثال , مأخوذ من أسئلة شائعة عن روبي:
$ irb
irb(main):001:0> class Test
irb(main):002:1> # public by default
irb(main):003:1* def func
irb(main):004:2> 99
irb(main):005:2> end
irb(main):006:1>
irb(main):007:1* def ==(other)
irb(main):008:2> func == other.func
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0>
irb(main):012:0* t1 = Test.new
=> #<Test:0x34ab50>
irb(main):013:0> t2 = Test.new
=> #<Test:0x342784>
irb(main):014:0> t1 == t2
=> true
irb(main):015:0> # now make `func` protected, still works
irb(main):016:0* # because protected allows the other reference
irb(main):017:0* class Test
irb(main):018:1> protected :func
irb(main):019:1> end
=> Test
irb(main):020:0> t1 == t2
=> true
irb(main):021:0> # now make `func` private
irb(main):022:0* class Test
irb(main):023:1> private :func
irb(main):024:1> end
=> Test
irb(main):025:0> t1 == t2
NoMethodError: private method `func' called for #<Test:0x342784>
from (irb):8:in `=='
from (irb):25
from :0
irb(main):026:0>
الأصناف قابلة للتعديل
أصناف روبي قابلة للتعديل . يمكنك التعديل عليهم ، الاضافة لهم ، التعديل عليهم في اي وقت.
حتى الأصناف الأساسية كصنف Fixnum ، أو حتى صنف Object, الأب لكل الأصناف . ريلز تقوم بتعريف العديد من الاجرائيات للتعامل مع الوقت مأخوذة من Fixnum. شاهد المثال التالي :
class Fixnum
def hours
self * 3600 # number of seconds in an hour
end
alias hour hours
end
# 14 hours from 00:00 January 1st
# (aka when you finally wake up ;)
Time.mktime(2006, 01, 01) + 14.hours # => Sun Jan 01 14:00:00
اسماء مضحكة للاجرائيات
في روبي ، مسموح لاسماء الاجرائيات ان تنتهي باشارة تعجب أو اشارة استفهام. لسهولة الفهم ، الاجرائيات التي تجيب على سؤال (مثلاً. Array#empty? تعيد true إذا كان المتلقي فارغاً) تنتهي باشارة استفهام . من المحتمل بأن تنتهي الاجارئيات “الخطرة” ( مثل الاجارئيات التي تقوم بالتعديل على self أو الأوامر مثل,exit! إلى آخر الأمثلة.) باشارة تعجب .
جميع الاجرائيات التي تغيير من متحولاتها لا تنتهي باشارة تعجب . Array#replace يقوم باستبدال نحتوى المصفوفة بمحتوى مصفوفة اخرى . لايمكن ان يجدي وجود مثل هذه الاجرائية التي لاتقوم بالتعديل على self.
اجرائيات Singleton
اجرائيات Singleton هي اجرائيات خاصة بالعنصر الذي قام بانشائها . وهي متوفرة فقط للعنصر الذي قام بتعريفها
class Car
def inspect
"Cheap car"
end
end
porsche = Car.new
porsche.inspect # => Cheap car
def porsche.inspect
"Expensive car"
end
porsche.inspect # => Expensive car
# Other objects are not affected
other_car = Car.new
other_car.inspect # => Cheap car
الاجرائيات المفقودة
روبي لا تيأس عندما لا تجد اجرائية تجيب على رسالة معينة .
تقوم باستدعاء اجرائية method_missing ملحقة باسم الاجرائية التي لم تجدها بالاضافة إلى الـ (arguments).
بشكل افتراضي تقوم اجرائية باطلاق استثناء NameError , و لكن يمكنك التعديل عليها لتتناسب بشكل اكبر مع برنامجك ، و العديد من المكاتب تفعل ذلك. إليك المثال التالي :
# id is the name of the method called, the * syntax collects
# all the arguments in an array named 'arguments'
def method_missing( id, *arguments )
puts "Method #{id} was called, but not found. It has " +
"these arguments: #{arguments.join(", ")}"
end
__ :a, :b, 10
# => Method __ was called, but not found. It has these
# arguments: a, b, 10
المثال السابق يقوم فقط بطباعة معلومات الطلب ، لكن لك الحرية في معالجة الرسالة بأي شكل تجده مناسباً .
تمرير الرسائل ، لا استدعاء التوابع
إن استدعاء الاجرائيات هو بالحقيقة رسالة إلى عنصر آخر:
# This
1 + 2
# Is the same as this ...
1.+(2)
# Which is the same as this:
1.send "+", 2
الكتل هي عناصر , لكنها لا تعلم بعد
الكتل ( المغلقة ، حقاً ) تستخدم بشكل كبير جداً في المكتبة القياسية. لاستدعاء كتلة
، يمكنك استخدام yield, أو يمكنك جعلها Proc باضافة معامل خاص لقائمة المعاملات كالتالي :
def block( &the_block )
# Inside here, the_block is the block passed to the method
the_block # return the block
end
adder = block { |a, b| a + b }
# adder is now a Proc object
adder.class # => Proc
يمكنك انشاء كتل خارج استدعاءات الاجرائيات ، أيضاً ، باستدعاء Proc.new مع الكتلة أو باستدعاء اجرائية lambda .
بالشكل نفسه ، الاجرائيات هي عناصر في طريقة الانشاء:
method(:puts).call "puts is an object!"
# => puts is an object!
المعاملات هي محلول قواعدي (Operators are syntactic sugar)
معظم المعاملات في روبي هي محلول قواعدي ( مع بعض الأسبقة ) لاستدعاءات الاجرائية. يمكنك على سبيل المثال أن تقوم باعادة كتابة اجارئية معامل الجمع ( + ) :
[Most operators in Ruby are just syntactic sugar (with some precedence rules) for method calls. You can, for example, override Fixnums + method]
class Fixnum
# يمكنك لكن لا تقم بفعلها
def +( other )
self - other
end
end
لست بحاجة لمعامل الجمع الخاص بـ C++'s operator+.
يمكنك الحصول على اسلوب المصفوفة للوصول إذا ما قمت بتعريف الاجرائية [] و []=.
لتعريف unary + و – (فكر بـ +1 و -2), فيجب عليك تعريف كل من الاجرائتين +@ و -@ , على التوالي.
المعاملات التالية ليست معاملات قابلة للتعديل. فهي ليست اجرائيات ، و لايمكنك اعادة تعريفها :
=, .., ..., !, not, &&, and, ||, or, !=, !~, ::
بالاضافة فإن , +=, *= إلى أخر السلسلة. هي فقط اختصارات لكل من
var = var + other_var, var = var * other_var, إلى آخر السلسلة. و لذلك لايمكن اعادة تعريفها و التعديل عليها.
البحث عن المزيد من المعلومات
عندما تتكون لديك المعرفة لمفاهيم روبي و ترغب بالمزيد يمكنك التوجه إلى قسم التوثيق الخاص باللغة .
