目次
1. نظرة عامة على وراثة بايثون
في بايثون، الوراثة هي الآلية التي يرث فيها الفئة الفرعية الوظائف والخصائص من الفئة الأم. وبذلك يتحسن إعادة استخدام الشيفرة وتزداد كفاءة الصيانة. وهي أحد المفاهيم المهمة في البرمجة الكائنية (OOP)، وتفيد بشكل خاص في تطوير الأنظمة الكبيرة والمشاريع طويلة الأمد.الدور الأساسي للوراثة
- إعادة استخدام الشيفرة: لأنه يمكن استخدام وظائف الفئة المكتوبة مرة واحدة في فئات أخرى، يمكن تجنب تكرار الشيفرة.
- سهولة الصيانة: لأن تغييرات الفئة الأم تنعكس تلقائيًا على الفئة الفرعية، يمكن إجراء التعديلات وتوسيع الوظائف بكفاءة.
class ParentClass:
def greet(self):
print("مرحبًا، هذه الفئة الأم.")
class ChildClass(ParentClass):
def greet(self):
print("مرحبًا، هذه الفئة الفرعية.")
في هذا المثال، ChildClass
يكتب فوق طريقة ParentClass
. وبما أن طريقة greet
تم تجاوزها، فإن الفئة الفرعية تعرض تحية مخصصة.2. الوراثة الأحادية في بايثون
الوراثة الأحادية هي الشكل يرث فيه صف فرعي وظائف من صف أب واحد. هذا هو الشكل الأساسي للوراثة في بايثون، ويمكنه الحفاظ على بساطة الكود مع إتاحة القابلية للتوسيع.الصيغة الأساسية للوراثة الأحادية ومثال
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
def describe(self):
print(f"هذه السيارة لونها {self.color} من نوع {self.brand}.")
class ElectricCar(Car):
def __init__(self, brand, color, battery_size):
super().__init__(brand, color)
self.battery_size = battery_size
def describe_battery(self):
print(f"سعة البطارية هي {self.battery_size}kWh.")
في هذا المثال، يورث الصف ElectricCar
وظائف الصف Car
مع إضافة وظيفة شرح سعة البطارية. يتم استخدام super()
لاستدعاء مُنشئ الصف الأب وت初始化 الخصائص المشتركة (العلامة التجارية واللون).3. تجاوز الطريقة
التجاوز هو وظيفة تسمح للصف الفرعي بإعادة تعريف طريقة الصف الأب. وبهذا يمكن الاستفادة من طريقة الصف الأب مع تعديل سلوكها في الصف الفرعي.مثال على التجاوز
class Animal:
def speak(self):
print("صوت الحيوان")
class Dog(Animal):
def speak(self):
print("هو هو!")
في هذا المثال، Dog
فئة تقوم بتجاوز طريقة speak
في فئة Animal
. وبالتالي، عند إنشاء كائن من فئة Dog
يتم طباعة “هو هو!”، بينما عند إنشاء كائن من فئة Animal
يتم عرض “صوت الحيوان”.4. الوراثة المتعددة
الوراثة المتعددة يمكن لفئة فرعية واحدة أن ترث من فئات أصلية متعددة. هذا يسمح بدمج وظائف فئات مختلفة في فئة واحدة، لكن قد يصبح التنفيذ معقدًا، لذا يجب الحذر.أمثلة على الوراثة المتعددة وملاحظات
class A:
def greet(self):
print("تحية A")
class B:
def greet(self):
print("تحية B")
class C(A, B):
pass
c = C()
c.greet() # "تحية A" يتم عرضها(وفقًا لـ MRO، يتم إعطاء الأولوية للفئة الأولى)
في بايثون، يحدد MRO(Method Resolution Order) أي طريقة من الفئات الأصلية سيتم استدعاؤها. للتحقق من هذا الترتيب، استخدم C.mro()
. الوراثة المتعددة قوية، لكن يجب استخدامها مع مراعاة الصراعات بين الفئات الأصلية وترتيب الطرق.
5. مثال عملي باستخدام الوراثة
الوراثة مفيدة في العديد من الحالات حتى في البرمجة اليومية. على سبيل المثال، في نظام إدارة موظفي الشركة، يمكن من خلال وراثة فئة الموظف الأساسية إلى فئة تحمل منصبًا معينًا تحقيق إعادة استخدام الكود وتوسيع وظائفه.مثال عملي لنظام إدارة الموظفين
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
def fullname(self):
return f'{self.first} {self.last}'
class Manager(Employee):
def __init__(self, first, last, pay, employees=None):
super().__init__(first, last, pay)
self.employees = employees if employees is not None else []
def add_employee(self, employee):
if employee not in self.employees:
self.employees.append(employee)
def print_employees(self):
for emp in self.employees:
print(emp.fullname())
في هذا المثال، ترث فئة Manager
فئة Employee
وتضيف وظائف إدارة الموظفين. يتم الحفاظ على الوظائف المشتركة للفئة الأم مع توسيع الوظائف لتتناسب مع المنصب المحدد.6. أفضل ممارسات الوراثة ومقارنة بالتركيب
الوراثة قوية جدًا، ولكن إذا استخدمت بشكل مفرط قد تؤدي إلى تعقيد الكود. خاصةً، قد تجعل الوراثة المتعددة علاقات بين الفئات معقدة، لذا يجب استخدامها بحذر. في مثل هذه الحالات، يُنصح باستخدام التركيب بدلاً من الوراثة.مثال على التركيب
التركيب هو نمط تصميم حيث تمتلك فئة فئة أخرى كجزء (مثيل) لتفويض الوظائف.class Engine:
def start(self):
print("تم تشغيل المحرك.")
class Car:
def __init__(self, engine):
self.engine = engine
def start(self):
self.engine.start()
engine = Engine()
car = Car(engine)
car.start() # "تم تشغيل المحرك." يتم عرضها
بهذه الطريقة، يكون التركيب هو الطريقة لمشاركة الوظائف بين الفئات دون استخدام الوراثة. من خلال إعطاء الفئات فقط الوظائف المطلوبة، يصبح الكود أكثر مرونة وسهولة في الإدارة.