✨ الوراثة في البايثون: قوة إعادة الاستخدام والتنظيم 🚀

مرحباً بك في درس اليوم! إذا كنت قد تساءلت يوماً كيف يمكن للبرامج الكبيرة أن تكون منظمة وسهلة الصيانة، فإن الإجابة غالباً ما تكمن في مفهوم الوراثة (Inheritance). الوراثة هي واحدة من الركائز الأساسية للبرمجة كائنية التوجه (OOP)، وهي تمكننا من بناء برامج أكثر كفاءة ونظافة. في هذا الدرس، سنتعلم كيف نستخدم هذه القوة في بايثون.


🤔 ما هي الوراثة (Inheritance)؟

ببساطة شديدة، الوراثة هي آلية تسمح لنا بإنشاء فئة جديدة (فئة فرعية) تستند إلى فئة موجودة مسبقاً (فئة أساسية). الفئة الفرعية ترث جميع السمات (الخصائص) والسلوكيات (الدوال) من الفئة الأساسية. هذا يشبه إلى حد كبير كيف يرث الطفل بعض الصفات من والديه!

الفائدة الكبرى: بدلاً من كتابة نفس الكود مراراً وتكراراً، نكتبه مرة واحدة في الفئة الأساسية ثم نعيد استخدامه في فئات متعددة. هذا يجعل الكود:

  • أقصر: أقل تكراراً.
  • أكثر تنظيماً: أسهل في الفهم والتعديل.
  • أسهل في الصيانة: التعديل في مكان واحد يؤثر على جميع الفئات التي ترث منه.

🔑 المصطلحات الأساسية التي يجب معرفتها

قبل أن نتعمق، دعنا نتعرف على المصطلحات التي سنستخدمها طوال الدرس:

  • الفئة الأساسية (Parent Class / Base Class): الفئة الأصلية التي يتم وراثة خصائصها ودوالها.
  • الفئة الفرعية (Child Class / Derived Class): الفئة الجديدة التي ترث من الفئة الأساسية. يمكنها أن تمتلك خصائص ودوال إضافية خاصة بها.

📝 كتابة أول فئة فرعية في بايثون

لإنشاء فئة فرعية، نستخدم بناء جملة بسيط جداً. نضع اسم الفئة الأساسية بين قوسين بعد اسم الفئة الفرعية.

لنفترض أن لدينا فئة أساسية تسمى Animal (حيوان).

# الفئة الأساسية (Parent Class)
class Animal:
    def __init__(self, name):
        self.name = name  # خاصية الاسم

    def speak(self):
        print("...")  # صوت عام غير محدد للحيوان

الآن، لننشئ فئة فرعية تسمى Dog (كلب) ترث من Animal.

# الفئة الفرعية (Child Class) ترث من Animal
class Dog(Animal): # لاحظ (Animal) داخل الأقواس
    pass  # كلمة pass تعني أن الفئة فارغة حالياً، لكنها ورثت كل شيء من Animal

دعنا نختبر ما حدث. لقد ورثت Dog المُنشَئ __init__ ودالة speak تلقائياً.

# إنشاء كائن من الفئة الفرعية Dog
my_dog = Dog("Rex")

# يمكننا استخدام الدوال الموروثة
print(my_dog.name)  # سيطبع: Rex
my_dog.speak()      # سيطبع: ...

كما ترى، على الرغم من أننا لم نعرف أي دوال داخل Dog، إلا أن الكائن استطاع استخدام الدوال الموروثة! هذه هي قوة الوراثة.


💪 توسيع functionality الفئة الفرعية

القوة الحقيقية للفئة الفرعية تكمن في قدرتها على:

  1. إضافة دوال وخصائص جديدة لا وجود لها في الفئة الأساسية.
  2. تعديل (إعادة تعريف) الدوال الموروثة لتناسبها بشكل أفضل.

1. إضافة دالة جديدة

لنجعل فئة Dog أكثر تحديداً بإضافة دالة جديدة تسمى fetch.

class Dog(Animal):
    # إضافة دالة جديدة خاصة بالكلب فقط
    def fetch(self, item):
        print(f"{self.name} is fetching the {item}!")

# الاختبار
my_dog = Dog("Rex")
my_dog.speak()  # موروثة: تطبع ...
my_dog.fetch("ball")  # جديدة: تطبع Rex is fetching the ball!

2. تعديل الدوال الموروثة (Method Overriding)

الدالة speak في Animal تطبع ...، لكننا نريد أن ينبح الكلب! يمكننا إعادة تعريف الدالة داخل الفئة الفرعية. هذه العملية تسمى "تجاوز الدالة" (Method Overriding).

class Dog(Animal):
    # تجاوز دالة speak الموروثة لتصبح مناسبة للكلب
    def speak(self):
        print(f"{self.name} says Woof!")

    def fetch(self, item):
        print(f"{self.name} is fetching the {item}!")

# الاختبار
my_dog = Dog("Rex")
my_dog.speak()  # الآن سيطبع: Rex says Woof!

🦸‍♂️ استخدام الدالة super()

ماذا لو أردنا إضافة سلوك إلى الدالة الموروثة بدلاً من استبدالها بالكامل؟ على سبيل المثال، نريد أن ينبح الكلب، ولكننا أيضاً نريد تنفيذ الكود الأصلي الموجود في Animal.speak().

هنا تأتي دور الدالة السحرية super(). تسمح لنا باستدعاء دوال من الفئة الأساسية.

لنفترض أننا عدلنا المُنشِئ في Animal ليطبع رسالة.

class Animal:
    def __init__(self, name):
        self.name = name
        print("An animal has been created!")  # رسالة جديدة

    def speak(self):
        print("...")

إذا عرفنا المُنشئ في Dog بدون super()، سنقوم بتجاوزه وسنخسر الرسالة.

class Dog(Animal):
    def __init__(self, name, breed):
        self.name = name
        self.breed = breed # خاصية جديدة للسلالة
        # لقد تجاوزنا __init__ من Animal، لذا لن تطبع الرسالة

الحل هو استخدام super() لاستدعاء منشئ الفئة الأساسية أولاً.

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # استدعاء منشئ الفئة الأساسية لتعيين الاسم وطباعة الرسالة
        self.breed = breed      # ثم إضافة الخاصية الجديدة

    def speak(self):
        print(f"{self.name} says Woof!")

# الاختبار
my_dog = Dog("Rex", "German Shepherd")
# سيطبع:
# An animal has been created!
print(my_dog.breed) # German Shepherd

🧪 مثال عملي شامل

لنجمع كل ما تعلمناه في مثال أوضح. لننشئ فئة أساسية Vehicle (مركبة) وفئتين فرعيتين Car (سيارة) و Bicycle (دراجة).

# الفئة الأساسية
class Vehicle:
    def __init__(self, brand, model):
        self.brand = brand
        self.model = model

    def start_engine(self):
        print("Engine starting... Vroom!")

# الفئة الفرعية Car
class Car(Vehicle):
    def __init__(self, brand, model, num_doors):
        super().__init__(brand, model) # نمرر brand و model للفئة الأساسية
        self.num_doors = num_doors

    # تجاوز الدالة لتناسب السيارة
    def start_engine(self):
        print(f"The {self.brand} {self.model}'s engine is purring...")

# الفئة الفرعية Bicycle
class Bicycle(Vehicle):
    # الدراجة ليس لها محرك، لذا نتجاوز الدالة لتفعل شيئاً مختلفاً
    def start_engine(self):
        print("A bicycle doesn't have an engine! Start pedaling!")

# الاختبار
my_car = Car("Toyota", "Camry", 4)
my_bike = Bicycle("Trek", "Mountain")

my_car.start_engine()  # The Toyota Camry's engine is purring...
my_bike.start_engine() # A bicycle doesn't have an engine! Start pedaling!

🎯 خلاصة الدرس

تهانينا! لقد تعلمت اليوم مفهومًا قويًا جداً في البرمجة. باختصار:

  • الوراثة تمكننا من إنشاء فئات جديدة بناءً على فئات موجودة.
  • الفئة الفرعية ترث من الفئة الأساسية.
  • يمكننا تجاوز الدوال الموروثة لتخصيص السلوك.
  • الدالة super() تساعدنا في استدعاء وإضافة إلى دوال الفئة الأساسية.

ماذا سنتعلم في الدرس القادم؟

الوراثة هي أولى أركان البرمجة الكائنية. في الدرس القادم، سنتعمق في ركن آخر لا يقل أهمية وهو تعدد الأشكال (Polymorphism). سنرى كيف يمكن للكائنات من فئات مختلفة أن تستجيب لنفس الاستدعاء (نفس اسم الدالة) بطرق مختلفة، مما يجعل كودنا أكثر مرونة وقوة. استعد لاكتشاف سحر تعدد الأشكال!