تعدد الأشكال
أمر واحد، وكل كائن ينفّذه بطريقته. ⏱ نحو 20 دقيقة.
- تشرح تعدد الأشكال بمثال من الحياة.
- تكتب دالة بالاسم نفسه في كلاسات مختلفة.
- تستدعي الدالة نفسها على قائمة كائنات مختلفة.
- تلخّص مبادئ البرمجة الشيئية الأربعة.
١أمر واحد، وأشكال كثيرة
تقول للطلاب «قدّموا أنفسكم»، فيقول كل واحد كلامًا مختلفًا. الأمر واحد، والتنفيذ يختلف حسب الشخص. هذا هو تعدد الأشكال: دالة بالاسم نفسه في كلاسات مختلفة، وكل كلاس ينفّذها بطريقته.
class Dog: def speak(self): print("هو هو") class Cat: def speak(self): print("مياو") for animal in [Dog(), Cat(), Dog()]: animal.speak()
الحلقة لا تسأل «هل هذا كلب أم قط؟». تكتب animal.speak() فقط، وكل كائن يعرف ما يفعله.
٢مع الوراثة: الأشكال الهندسية
غالبًا نجمع تعدد الأشكال مع الوراثة: الأب يحدد اسم الدالة، وكل ابن يعيد تعريفها بطريقته:
class Shape: def area(self): return 0 class Square(Shape): def __init__(self, side): self.side = side def area(self): return self.side * self.side class Circle(Shape): def __init__(self, r): self.r = r def area(self): return round(3.14 * self.r * self.r, 2) shapes = [Square(4), Circle(2), Square(3)]for s in shapes: print(s.area())
٣لماذا هو مفيد؟
لو أضفنا شكلًا جديدًا (مستطيلًا مثلًا) فإننا نكتب كلاسه فقط، ولا نغيّر الحلقة أبدًا. قارن:
for s in shapes: if type(s) == Square: print(s.side * s.side) elif type(s) == Circle: print(3.14 * s.r * s.r)
for s in shapes: print(s.area())
في الطريقة الأولى نعدّل الحلقة مع كل شكل جديد. في الثانية الحلقة ثابتة، وكل شكل يحسب مساحته بنفسه.
٤ملخص البرمجة الشيئية
| المبدأ | الفكرة | في بايثون |
|---|---|---|
| الكلاس والكائن | قالب ونسخ منه | class و Car() |
| التغليف | حماية البيانات | self.__balance |
| الوراثة | الابن يأخذ من الأب | class Student(Person) |
| تعدد الأشكال | أمر واحد وتنفيذ مختلف | دالة بالاسم نفسه في كل كلاس |
📎 للاستزادة (اختياري): أنت تستخدم تعدد الأشكال منذ البداية
الدالة len تعمل مع النص ومع القائمة، والعلامة + تجمع الأعداد وتلصق النصوص. أمر واحد وسلوك يختلف حسب النوع.
توقّع وتحقّق
ما معنى تعدد الأشكال؟
في الحلقة for s in shapes: print(s.area()) من يحدد طريقة حساب المساحة؟
area بطريقته.عند إضافة شكل جديد، ماذا نكتب؟
أي مبدأ يحمي البيانات داخل الكائن؟
الخلاصة
- تعدد الأشكال: دالة بالاسم نفسه، وكل كلاس ينفّذها بطريقته.
- نستدعي الدالة على كل الكائنات دون فحص نوعها.
- إضافة نوع جديد لا تحتاج تعديل الحلقة.
- المبادئ الأربعة: الكلاس والكائن، والتغليف، والوراثة، وتعدد الأشكال.
تحدٍّ برمجي: الموظفون والرواتب
متقدماكتب كلاسين: Employee و Manager، لكل منهما __init__ تحفظ الراتب الأساسي، ودالة pay. موظف عادي: pay تُرجع الراتب كما هو. المدير: pay تُرجع الراتب + 2000. ضع في قائمة موظفًا براتب 5000 ومديرًا براتب 7000، واطبع pay لكل منهما بحلقة، ثم المجموع.
- Manager يرث من Employee.
- أعد تعريف pay في Manager.
- الحلقة تستدعي
p.pay()فقط. - اطبع: المجموع: ثم القيمة.
ابدأ من هذا الكود، واضغط ▶ شغّل هنا لتكتب حلّك وتجرّبه مباشرة:
class Employee: def __init__(self, salary): self.salary = salary
💡 تلميح 1
class Manager(Employee):💡 تلميح 2
return self.salary + 2000حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.
class Employee: def __init__(self, salary): self.salary = salary def pay(self): return self.salary class Manager(Employee): def pay(self): return self.salary + 2000 staff = [Employee(5000), Manager(7000)]total = 0for p in staff: print(p.pay()) total += p.pay()print("المجموع:", total)