في هذا الجزء، سنكمل مشوارنا في طريق تعلم أساسيات البرمجة بلغة روبي. البرمجة غرضية التوجه (أو كائنية المنحى) موضوع كبير ومتشعب (طول هذه التدوينة يشير إلى ذلك!)، ولن نتمكن من إعطائه حقه ضمن هذه السلسلة. لذلك، سنركز على أساسيات استخدام البرمجة غرضية التوجه ضمن لغة روبي.
بالإضافة إلى هذه التدوينة، تتكون السلسلة من التدوينات التالية:
- تعلم أساسيات البرمجة بلغة روبي – مُقدِّمة
- تعلم أساسيات البرمجة بلغة روبي – أهلاً بالعالم!
- تعلم أساسيات البرمجة بلغة روبي – ثوابت، متغيرات، وأنواع بيانات
- تعلم أساسيات البرمجة بلغة روبي – بنى البيانات، بعض التكرار، وقليل من المنطق
- تعلم أساسيات البرمجة بلغة روبي – إرشادات لما بعد اﻷساسيات
أولا: الطُرق (Methods)
كما في لغات البرمجة الأخرى، يوفر استخدام الطرق وسيلة لتنظيم الشيفرة البرمجية وتعزيز إعادة الاستخدام بدلاً من إعادة الكتابة. بكلمات أخرى، بدلاً من إنشاء أقسام طويلة من التعليمات البرمجية، يتم تنظيمها إلى مجموعات منطقية يمكن استدعاؤها عند الحاجة، وإعادة استخدامها دون الحاجة إلى إعادة كتابة تلك التعليمات البرمجية نفسها مراراً وتكراراً.
لاستخدام طريقة خاصة بك في روبي، كل ما عليك فعله هو الإعلان عنها ثم استدعاؤها.
puts "The art of simplicity is a puzzle of complexity."
end
talk
# Prints the following:
# The art of simplicity is a puzzle of complexity.
عادة ما تصمم الطرق لتنفذ مهمة ما على مُعامِل (parameter) أو أكثر.
puts "Hi, " + first_name + " " + last_name + "!"
end
say_hi_to("Ruby", "Newbie") # Prints: Hi, Ruby Newbie!
تستخدم عبارة return لإرجاع قيمة ما من الطريقة. من المهم معرفة أنه لا يمكن لأي طريقة إرجاع أكثر من قيمة واحدة. إذا كان لا بد من إرجاع عدة قيم، فيمكن مثلاً وضع هذه القيم في مصفوفة وإرجاع تلك المصفوفة.
return "Ruby Newbie"
end
puts get_name # Prints : Ruby Newbie
من الجدير بالذكر أن روبي ستعيد قيمة آخر تعبير في الطريقة بشكل افتراضي. لذلك، يمكننا كتابة طريقة get_name البسيطة في المثال السابق كما يلي:
"Ruby Newbie"
end
ثانيا: الأصناف (Classes) والكائنات (Objects)
يمكن النظر إلى الصنف على أنه “المخطط” الذي ستُبنى الكائنات استناداً عليه. يتم تعريف الصنف في روبي باستخدام الكلمة المفتاحية class، متبوعة بإسم الصنف مبدوءً بحرف كبير (upper case)، وينتهي التعريف بـend
end
يمكن إنشاء كائن من الصنف Person كما يلي:
قد يبدو الكائن someone خالياً وغير قادر على القيام بأي شيء، لكن الحقيقة غير ذلك. لنقم ببعض التجارب في irb
=> -606876258
>> someone.nil?
=> false
>> someone.is_a? Integer
=> false
>> someone.class
=> Person
كل صنف في روبي هو صنف فرعي (subclass) من الصنف Object، وبذلك فهو يكتسب كل طرقه عبر الوراثة (inheritance) – المزيد عن ذلك في آخر التدوينة.
=> ["inspect", "tap", "clone", "poc", "public_methods", "__send__", "object_id", "instance_variable_defined?", "equal?", "freeze", "extend", "send", "say_hi_to", "methods", "pretty_print", "hash", "taguri", "dup", "to_enum", "instance_variables", "pretty_print_cycle", "eql?", "taguri=", "instance_eval", "id", "singleton_methods", "ri", "taint", "pretty_print_inspect", "to_yaml_style", "enum_for", "frozen?", "instance_variable_get", "instance_of?", "display", "to_a", "method", "type", "to_yaml_properties", "instance_exec", "protected_methods", "==", "===", "instance_variable_set", "kind_of?", "respond_to?", "to_yaml", "to_s", "class", "po", "pretty_print_instance_variables", "private_methods", "=~", "tainted?", "__id__", "untaint", "nil?", "pretty_inspect", "is_a?", "talk"]
معلومة: ذكرنا سابقا أن كل شيء في روبي عبارة عن كائن، وهذا يشمل اﻷصناف أيضاً. كل صنف هو نسخة من الصنف Class.
ثالثا: دمج الطرق والمتغيرات مع الكائنات
ماذا إذا أردنا أن نجعل كائنات الصنف Person أكثر إثارة للإهتمام بإضافة طرقنا الخاصة؟
def say_hi
puts "Hi!"
end
end
تجدر الإشارة إلى طريقة initialize، وهي طريقة معيارية في لغة روبي، وهي أول طريقة يتم استدعاؤها بعد الفراغ من تهيئة الكائن الجديد (أي بعد استدعاء طريقة new). هذه الطريقة مفيدة بشكل خاص إذا أردنا حدوث شيء ما عند إنشاء الكائن أو إذا كان هنالك مُعامِلات تود تمريرها إليه وقت إنشائه.
def initialize
puts "I'm.. I'm alive!"
end
def say_hi
puts "Hi!"
end
end
متغيرات الكائن – أو النسخة – (instance variables) هي متغيرات يتم تعريفها في الصنف وتكون متوفرة لكل كائن من هذا الصنف فقط. يتم تعريف متغيرات الكائن في روبي بإضافة @ أمام اسم المتغير. لجعل هذه المتغيرات متاحة للقراءة من خارج الصنف المعين، يجب وضعها في طرق استرجاع (getter methods).
def initialize(name, age)
@name = name
@age = age
end
def name
@name
end
def age
@age
end
end
اﻵن بإمكاننا إنشاء كائن جديد مع إعطائه إسماً وعمراً، ومن ثمّ التحقق من إسمه وعمره.
puts someone.name # Prints: Ruby Newbie
puts someone.age # Prints: 13
إذاً بإمكاننا قراءة قيمة متغير كائن، لكن ماذا إذا ما أردنا تغييرها؟ في هذه الحالة، علينا استخدام طرق تعيين (setter methods). من الممكن فعل ذلك كما في الشيفرة أدناه، لكن ﻻ تتعب نفسك بكتابة هذه الشيفرة، ﻷن هنالك طريقة أسهل. فقط تابع القراءة!
def initialize(name, age)
@name = name
@age = age
end
def name
@name
end
def age
@age
end
def name=(value)
@name = value
end
def age=(value)
@age = age
end
end
بما أن العديد من متغيرات الكائن بحاجة إلى طرق استرجاع وتعيين، توفر روبي بعض الطرق المريحة:
- attr_accessor: تتيح قراءة وتغيير قيمة المتغير.
- attr_reader: تتيح قراءة قيمة المتغير.
- attr_writer: تتيح تغيير قيمة المتغير.
اﻵن أصبح بإمكاننا كتابة الشيفرة السابقة بشكل أفضل:
attr_accessor :name, :age
def initialize(name, age)
@name = name
@age = age
end
end
سطر واحد أغنانا عن كتابة 4 طرق.أمر جميل، أليس كذلك؟
رابعا: دمج الطرق والمتغيرات مع الأصناف
متغيرات الصنف (class variables) هي متغيرات مشتركة بين كل كائنات صنف معين. بمعنى آخر، هناك نسخة واحدة من كل متغير صنف وهي متاحة لجميع كائنات ذلك الصنف. يتم تعريف متغيرات الصنف بإضافة @@ أمام اسم المتغير، ويجب تهيئتها (عبر تعيين قيمة لها مثلا) قبل استخدامها. ماذا إذا ما أردنا جعل متغير صنف متاحاً من خارج هذا الصنف؟ كما في حالة متغير الكائن، علينا وضعه في طريقة استرجاع أو تعيين حسب الرغبة. هناك نوع خاص من الطرق يعرف بالطرق الصنفية (class methods). تعمل هذه الطرق دون الحاجة إلى وجود نسخة من الصنف المعين، و تُعرّف بوضع اسم الصنف ثم نقطة أمام اسم الطريقة.
@@population = 0
def initialize
@@population += 1
end
def Person.population
@@population
end
end
puts Person.population # Prints: 0
someone = Person.new
puts Person.population # Prints: 1
someone_else = Person.new
puts Person.population # Prints: 2
خامسا: الوراثة (Inheritance)
تدعم لغة روبي الوراثة الموحدة (single inheritance)،أي أن الصنف الفرعي (subclass) يستطيع وراثة المتغيرات والطرق من صنف واحد فقط (superclass).
لنقم بإنشاء صنف جديد وجعله صنفاً فرعياً من الصنف Person الذي يحتوي المتغيرين name وage
end
اﻵن، يمكننا إنشاء كائن من الصنف Programmer وسيكون لديه نفس المتغيرات الموجودة في الصنف Person
puts programmer.name # prints: Ruby Newbie
puts programmer.age # Prints: 13
لكن ما الفائدة من الصنف Programmer هنا إذا كان مطابقاً للصنف Person؟ لنضف متغيراً خاصاً للمبرمجين.
attr_accessor :language
def initialize(name, age, language)
super(name, age)
@language = language
end
end
programmer = Programmer.new("Ruby Newbie", 13, "Ruby")
puts programmer.name # Prints: Ruby Newbie
puts programmer.age # Prints: 13
puts programmer.language # Prints: Ruby
في الشيفرة أعلاه، استخدمنا طريقة super مع المعاملَين name وage لنطلب من الصنف اﻷب Person إسناد القيم المعطاة للمتغيرين @name و@age
ما زال هنالك العديد من المفاهيم المتعلقة بالبرمجة غرضية التوجه التي يمكن الحديث عنها، ولكن بما أن الهدف من هذه التدوينة كان تقديم أبرز تلك المفاهيم وكيفية استخدامها في روبي، فسننهيها ها هنا. في الجزء القادم، سنختم السلسلة ونقدم قائمة ببعض المصادر والمراجع لمن أراد إكمال المشوار لما بعد اﻷساسيات.

عدد التعليقات 3
مقال جميل أخي و لي تعليق واحد في هذا المقام لجعل الأمور أوضح لو تم وضع بعض الرسوم التوضيحية لموضع الكائن و الفئة حتى تكون الأمور أسهل على المتعلمين
@عمر
شكراً على الاقتراح.
أتفق معك في أن وضع بعض الرسوم التوضيحية سيجعل الأمور أوضح خصوصاً لمن لم يتعرض لهذه المفاهيم من قبل، لكني آثرت التركيز على الأمثلة المكتوبة بلغة روبي لتوضيح قواعد وأساسيات استخدام البرمجة غرضية التوجه ضمن روبي ذاتها. وكما ذكرت في مقدّمة السلسلة، فيفضل أن يكون لدى القارئ “خلفية – ولو بسيطة – عن البرمجة بشكل عام، والبرمجة الغرضية التوجه بشكل خاص.”
على كل حال، لعلنا نستفيد من اقتراحك في كتابة درس خاص عن مفاهيم البرمجة الغرضية التوجه في المستقبل
جزاك الله خير …
على السلسلة الرائعة …
استفدت منها كثيراً … بالتوفيق
تعقيب واحد
[...] روابـــ(8)ــط September 23, 2009 at 8:08 pm | In روابــــــط | Leave a Comment سلام من الله عليكم ورحمته وبركاته ومغفرته ورضوانه * تسجيلات صوتيه لمبرمجين محترفين * مايكروسوفت تطلق محرك البحث الجديد Bing * بدائل الـ Rails * قاموس لغات البرمجة * Reading Ruby’s Standard Library for Fun and Profit * موقع يعرفك بامتدادات الملفات وبرامجها [File Extension] * Session Manager , أضافة جميلة للفايرفوكس تمكنك من حفظ جلسات معينة , واسترجاعها وقت الحاجة * RubyTips : يحتوي علي بعض الحلول الجميلة لبعض المشاكل * how to choose the right screenshot program * Wepopedia : الموسوعة الأولى للحاسب * جدول بلغات البرمجة * uniques ruby language features * The Groovy and Grails Podcast * Rip: A New Package Management System for Ruby * البرمجة غرضية التوجه في روبي [...]