الوراثة
في الدروس السابقة تعلمنا كيف ننشئ أصنافاً ونستخدم initialize والموصّلات. لكن ماذا لو أردنا إنشاء أصناف متشابهة تشترك في بعض الخصائص والسلوكيات؟ هل نُكرر الشيفرة في كل صنف؟ بالطبع لا! هنا تأتي الوراثة (Inheritance).
ما هي الوراثة؟
الوراثة هي آلية تسمح لصنف (يُسمى الصنف الابن) بأن يرث خصائص وسلوكيات صنف آخر (يُسمى الصنف الأب).
مثال من الحياة الواقعية
فكّر في الحيوانات:
- صنف أب: حيوان (له اسم، يأكل، ينام)
- صنف ابن: كلب (يرث من حيوان + يضيف النباح)
- صنف ابن: قط (يرث من حيوان + يضيف المواء)
الكلب والقط كلاهما حيوانات، لذا يشتركان في خصائص مثل الاسم والأكل والنوم. لكن لكل منهما سلوكه الخاص.
صيغة الوراثة
نستخدم الرمز < للوراثة:
مثال بسيط: الحيوان والكلب
بدون وراثة (الطريقة السيئة)
المشكلة: شيفرة مُكررة! إذا أردنا تعديل eat أو sleep، يجب تعديلها في كل صنف.
مع الوراثة (الطريقة الصحيحة)
الآن:
Dogيرثinitialize,eat,sleep, وnameمنAnimalDogيضيفbarkكسلوك خاص به- لا تكرار للشيفرة!
إضافة أصناف ابن أخرى
إعادة تعريف الدوال (Method Overriding)
يمكن للصنف الابن إعادة تعريف دالة موروثة لتغيير سلوكها:
استدعاء دالة الأب بـ super
أحياناً نريد توسيع سلوك الأب بدلاً من استبداله كلياً. نستخدم super لاستدعاء دالة الأب:
أشكال super المختلفة
التحقق من الوراثة
مثال عملي: نظام الموظفين
مثال عملي: أشكال هندسية
الناتج:
قواعد الوراثة في روبي
1. الوراثة الفردية فقط
روبي تدعم وراثة فردية فقط (صنف واحد يرث من صنف أب واحد):
ملاحظة: لمشاركة الشيفرة بين أصناف غير متعلقة، نستخدم الوحدات (Modules) - سنتعلمها في الدرس القادم.
2. كل الأصناف ترث من Object
3. الموصّلات موروثة أيضاً
جدول مقارنة
| المفهوم | الوصف | مثال |
|---|---|---|
| الصنف الأب | الصنف الذي يُورّث | class Animal |
| الصنف الابن | الصنف الذي يرث | class Dog < Animal |
< | رمز الوراثة | Child < Parent |
super | استدعاء دالة الأب | super(args) |
| Method Override | إعادة تعريف دالة موروثة | def speak; "هاو!"; end |
is_a? | التحقق من النوع مع الوراثة | dog.is_a?(Animal) |
superclass | الصنف الأب المباشر | Dog.superclass |
أخطاء شائعة
1. نسيان super في initialize
الصحيح:
2. استدعاء super بالمُعاملات الخاطئة
الصحيح:
3. محاولة الوراثة المتعددة
4. استدعاء دالة غير موجودة في الأب
متى نستخدم الوراثة؟
استخدم الوراثة عندما:
- يوجد علاقة "هو نوع من" (is-a relationship)
- الصنف الابن هو تخصص من الصنف الأب
- تريد مشاركة شيفرة بين أصناف متشابهة
لا تستخدم الوراثة عندما:
- لا يوجد علاقة "هو نوع من"
- تريد فقط مشاركة بعض الدوال (استخدم Modules)
ملخص
| المفهوم | الوظيفة |
|---|---|
class Child < Parent | إنشاء صنف يرث من آخر |
super | استدعاء دالة الأب |
super(args) | استدعاء مع مُعاملات محددة |
| Method Override | إعادة تعريف دالة موروثة |
is_a? | التحقق من الوراثة |
superclass | معرفة الصنف الأب |
ancestors | سلسلة الوراثة كاملة |
تمرين: نظام الحيوانات
حان وقت التطبيق! في محرر الشيفرة على اليسار:
المطلوب:
-
أنشئ صنف
Animalيحتوي على:attr_reader :nameinitialize(name)speakتطبع "صوت غير معروف"
-
أنشئ صنف
Dogيرث منAnimal:- إعادة تعريف
speakلتطبع "هاو هاو!"
- إعادة تعريف
-
أنشئ صنف
Catيرث منAnimal:- إعادة تعريف
speakلتطبع "مياو!"
- إعادة تعريف
-
أنشئ كلباً اسمه "بوبي" وقطاً اسمه "ميشو"
-
اطبع اسم كل حيوان ثم استدعِ speak
الناتج المتوقع:
تلميحات:
- ابدأ بـ
class Animalمعattr_reader :nameوdef initialize(name) - الكلب والقط يرثان:
class Dog < Animal - استخدم
putsداخلspeak - لا تنسَ استدعاء
.nameللطباعة:puts dog.name
تذكّر: الوراثة تسمح بإنشاء تسلسل هرمي من الأصناف. الصنف الابن يرث كل شيء من الأب ويمكنه إضافة أو تعديل السلوكيات. استخدم
superلاستدعاء دالة الأب عند الحاجة. في الدرس القادم سنتعلم الوحدات والـ Mixins لمشاركة الشيفرة بين أصناف غير متعلقة!