الوراثة (Inheritance) — البرمجة الكائنية
الوراثة (Inheritance)
الوراثة تسمح بإنشاء صنف جديد يبني على صنف موجود: يأخذ كل خصائصه ودواله، ثم يضيف أو يغيّر ما يحتاجه.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Cat(Animal): # Cat يرث من Animal
def speak(self): # إعادة تعريف (override)
return "مياو"Cat("ميمي").name تعمل رغم أن Cat لم يعرّف __init__، لأنه ورثها.
العلاقة "هو نوع من" (is-a)
استخدم الوراثة عندما يكون الصنف الجديد نوعاً من الأب فعلاً: القطة حيوان، الحساب التوفيري حساب بنكي. إذا لم تصح الجملة، فالوراثة اختيار خاطئ (سنرى البديل في درس التركيب).
super(): استدعاء دالة الأب
عندما يحتاج الابن خصائص إضافية، يعرّف __init__ خاصة به ويستدعي __init__ الأب أولاً:
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # يهيئ name
self.breed = breedإذا نسيت super().__init__، لن تُنشأ الخاصية name وستحصل على AttributeError لاحقاً.
يمكنك أيضاً توسيع دالة الأب بدل استبدالها:
def describe(self):
return super().describe() + f" من سلالة {self.breed}"فحص الأنواع
rex = Dog("ريكس", "هاسكي")
isinstance(rex, Dog) # True
isinstance(rex, Animal) # True: الكلب حيوان أيضاً
issubclass(Dog, Animal) # Trueالوراثة المتعددة
Python تسمح بالوراثة من أكثر من صنف: class Duck(Animal, Swimmer). ترتيب البحث عن الدوال يسمى MRO ويمكن رؤيته بـ Duck.__mro__. استخدمها بحذر؛ الاستخدام الشائع والآمن هو أصناف صغيرة تضيف قدرة واحدة (تسمى mixins).
متى تكون الوراثة مشكلة؟
سلاسل وراثة عميقة (أ ← ب ← ج ← د) تجعل فهم مصدر كل سلوك صعباً. اجعل الهرم ضحلاً.
تمرين
أنشئ صنف Employee (الاسم، الراتب، annual_salary())، ثم Manager يرث منه ويضيف bonus ويعيد تعريف annual_salary() مستخدماً super().
# الصنف الأب
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def speak(self):
return "صوت ما..."
def info(self):
return f"{self.name}, عمره {self.age} سنة"
# الصنف الابن
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # استدعاء constructor الأب
self.breed = breed
# Override - إعادة تعريف
def speak(self):
return "هاو هاو! 🐕"
def fetch(self):
return f"{self.name} يجلب الكرة!"
class Cat(Animal):
def speak(self):
return "مياو! 🐱"
def scratch(self):
return f"{self.name} يخدش!"
# استخدام
dog = Dog("بادي", 3, "جولدن")
cat = Cat("ميمي", 2)
print(dog.speak()) # هاو هاو!
print(cat.speak()) # مياو!
print(dog.info()) # بادي, عمره 3 سنة
print(dog.fetch())
# التحقق من النوع
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True
print(issubclass(Dog, Animal)) # True
# Multiple Inheritance
class Flyable:
def fly(self):
return "أطير! ✈️"
class Swimmable:
def swim(self):
return "أسبح! 🏊"
class Duck(Animal, Flyable, Swimmable):
def speak(self):
return "كواك كواك! 🦆"
duck = Duck("دونالد", 1)
print(duck.speak())
print(duck.fly())
print(duck.swim())اختبر فهمك