13.3 التوابع
أهداف التعلم
في نهاية هذا القسم، ينبغي أن تكون قادرًا على:
- كتابة توابع مُعاد تعريفها لتغيير سلوك التوابع الموروثة.
- استخدام
super()للوصول إلى توابع الصنف الأب. - تحديد تطبيقات تعدد الأشكال في استخدام التوابع والدوال.
إعادة تعريف التوابع
أحيانًا يرغب المبرمج في تغيير الدوال التي يرثها الصنف الفرعي. Mint هو صنف فرعي يشبه في وظائفه Plant، باستثناء دالة واحدة. يمكن للصنف الفرعي إعادة التعريف (override) لتابع من الصنف الأب عن طريق تعريف تابع بالاسم نفسه لتابع الصنف الأب.
مفاهيم تطبيقية
إعادة تعريف التوابع
الدالة super()
super() تابع خاص يوفر مثيل كائن مؤقتًا من الصنف الأب ليستخدمه الصنف الفرعي. يُستخدم super() عادةً لاستدعاء توابع الصنف الأب من صنف فرعي، ولا سيما في التابع __init__() الخاص بالصنف الفرعي لإسناد سمات المثيل الموروثة. مثال: super().__init__().
مفاهيم تطبيقية
استخدام super()
تأمل البرنامج التالي.
1 | class Polygon: |
2 | def __init__(self, num_sides=3): |
3 | self.num_sides = num_sides |
4 | |
5 | class Rectangle(Polygon): |
6 | def __init__(self, ln=1, wd=1): |
7 | super().__init__(4) |
8 | self.length = ln |
9 | self.width = wd |
10 | |
11 | class Square(Rectangle): |
12 | def __init__(self, side=1): |
13 | super().__init__(side, side) |
14 | self.side = side |
15 | |
16 | sq_1 = Square(5) |
17 | print(sq_1.num_sides) |
تعدد الأشكال
تعدد الأشكال (polymorphism) هو مفهوم وجود أشكال متعددة. في البرمجة، يمكن استخدام اسم واحد لوظائف متعددة. ضمن الوراثة، يُعد تعدد الأشكال أساس إعادة تعريف التوابع، حيث توجد توابع متعددة تحمل نفس الاسم.
مثال 13.1
تعدد الأشكال والوراثة
الاسم display() يقابل توابع متعددة. يحدد نوع صنف الكائن المستدعي أيَّ تابع display() سيُنفَّذ.
class Plant:
def display(self):
print("I'm a plant")
class Mint(Plant):
def display(self):
print("I'm a mint")
class Lavender(Mint):
def display(self):
print("I'm a lavender")
mint_1 = Mint()
mint_1.display()
lavender_1 = Lavender()
lavender_1.display()
إخراج الشِفرة هو:
I'm a mint
I'm a lavender
يمكن أيضًا استخدام تعدد الأشكال مع توابع الأصناف غير المرتبطة. يحدد نوع صنف الكائن المستدعي التابعَ الذي سيُنفَّذ.
مثال 13.2
تعدد الأشكال والتوابع
Tax و ContractTax هما صنفان غير مرتبطان، وكل منهما يُعرّف calc_tax(). لا يتم إعادة تعريف calc_tax() لأن ContractTax ليس موروثًا من Tax.
class Tax:
def __init__(self, value):
self.value = value
def calc_tax(self):
print("Calculating tax")
total = 0.10 * self.value # يُستبدل بالحساب
return total
class ContractTax:
def __init__(self, value):
self.value = value
def calc_tax(self):
print("Calculating contracts tax")
total = 0.15 * self.value # يُستبدل بالحساب
return total
my_tax = ContractTax(value=1000) # استبدل 1000 بأي قيمة
result = my_tax.calc_tax()
print(f"Total tax: ${result}")
إخراج الشِفرة هو:
Calculating contracts tax
Total tax: $150.00
يسمح تعدد الأشكال باستدعاء التوابع بأنواع مُعامِلات مختلفة. العديد من العوامل والدوال المُضمَّنة لديها هذه الفائدة.
مثال 13.3
تعدد الأشكال والدوال
يمكن استدعاء len() بأنواع متعددة، بما في ذلك القوائم والسلاسل النصية.
tree_list = ["ash", "hazel", "oak", "yew"]
tree_1 = tree_list[0]
print(len(tree_list))
print(len(tree_1))
إخراج الشِفرة هو:
4
3
مفاهيم تطبيقية
تعدد الأشكال في الممارسة
جرّب بنفسك
إعادة تعريف التوابع
بفرض وجود الصنف Pet، أنشئ صنف Bird موروثًا من Pet وصنف Finch موروثًا من Bird. أعد تعريف التابع display() في Bird و Finch بحيث يكون إخراج البرنامج:
Pet type: Bird
Bird type: Finch
جرّب بنفسك
استخدام super()
بفرض وجود الصنف Employee، أنشئ صنف Developer موروثًا من Employee مع التابعين __init__() و print_info() بحيث:
__init__()
- يستخدم
super()لاستدعاء التابع__init__()الخاص بـEmployeeلتهيئةe_idوhire_year. - يُسند
lang_xpباستخدام مُعامِل القائمةlang_xp.
print_info()
- يستخدم
super()لطباعةe_idوhire_year. - يطبع
"Language(s):"متبوعًا بـlang_xp.