كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف في بايثون 3
التعددية الشكلية (Polymorphism) هي إحدى المفاهيم الأساسية في البرمجة الكائنية التوجه (OOP)، وهي تعني أن كائنات مختلفة قد تتعامل مع نفس النداء (المتغير أو الوظيفة) بطرق مختلفة. في بايثون، يمكن تطبيق التعددية الشكلية على الأصناف (Classes) بشكل مرن للغاية، مما يسمح بإنشاء برامج أكثر قابلية للصيانة والتنظيم. في هذا المقال، سنتناول كيفية تطبيق التعددية الشكلية على الأصناف في بايثون 3، ونعرض العديد من الأمثلة التي تبرز كيفية استخدامها في الحياة العملية.
مفهوم التعددية الشكلية
التعددية الشكلية ببساطة تعني القدرة على استدعاء نفس الوظيفة أو العملية على كائنات من أصناف مختلفة. يمكننا أن نكتب الكود بطريقة تسمح للكائنات من أصناف مختلفة بتنفيذ نفس الوظيفة بشكل يختلف باختلاف النوع (Type) دون الحاجة إلى معرفة التفاصيل الداخلية لكل صنف.
في بايثون، هناك نوعان رئيسيان للتعددية الشكلية:
-
التعددية الشكلية عبر التوارث (Inheritance-based Polymorphism): حيث يتم توريث وظيفة معينة من صنف أب ويتم تخصيصها أو تعديلها في الأصناف الفرعية.
-
التعددية الشكلية عبر التعداد (Duck Typing): وهي خاصية يتمتع بها بايثون حيث لا يعتمد على النوع الصريح للمتغير بل على أسلوب استخدامه، أي إذا كان الكائن يتصرف بطريقة معينة، يمكن استدعاء وظيفته بغض النظر عن نوعه الفعلي.
التعددية الشكلية عبر التوارث
الطريقة الأكثر شيوعًا لتطبيق التعددية الشكلية في بايثون هي عن طريق التوارث. في هذا السياق، يمكن أن تقوم الأصناف الفرعية بتعديل أو تخصيص سلوك الدوال أو العمليات التي ورثتها من الصنف الأب. نعرض فيما يلي مثالًا بسيطًا يوضح كيفية تنفيذ ذلك.
مثال: التعددية الشكلية عبر التوارث
pythonclass Animal:
def speak(self):
raise NotImplementedError("Subclasses must implement this method")
class Dog(Animal):
def speak(self):
return "Woof"
class Cat(Animal):
def speak(self):
return "Meow"
def animal_sound(animal):
print(animal.speak())
dog = Dog()
cat = Cat()
animal_sound(dog) # Output: Woof
animal_sound(cat) # Output: Meow
في المثال السابق، لدينا صنف أب يُدعى Animal يحتوي على دالة speak التي لا تقوم بأي شيء ولكنها ترفع استثناء لإعلام الأصناف الفرعية بضرورة تنفيذ هذه الدالة. ثم، قمنا بإنشاء صنفين فرعيين هما Dog و Cat، اللذان نفذا دالة speak بطريقتين مختلفتين. في النهاية، نلاحظ أنه يمكن استدعاء دالة speak من خلال دالة animal_sound على كائنات من نوع Dog و Cat بشكل غير مرتبط بالصنف الأصلي، مما يحقق التعددية الشكلية.
التعددية الشكلية عبر التعداد (Duck Typing)
في بايثون، كما هو الحال في العديد من اللغات التي تعتمد على البرمجة الكائنية التوجه، لا يشترط على الكائنات أن تكون من صنف معين لاستخدامها في العمليات. في بايثون، يطلق على هذه الفكرة اسم “التعداد” أو “البرمجة عبر التعداد” (Duck Typing)، وهي تعني أنه إذا كان الكائن يتصرف مثل كائن معين، فيمكنه أن يُعامل ككائن من هذا النوع.
مثال: التعددية الشكلية عبر التعداد
pythonclass Bird:
def fly(self):
print("Flying like a bird")
class Airplane:
def fly(self):
print("Flying like an airplane")
def make_it_fly(flyable):
flyable.fly()
bird = Bird()
airplane = Airplane()
make_it_fly(bird) # Output: Flying like a bird
make_it_fly(airplane) # Output: Flying like an airplane
في هذا المثال، لدينا صنف Bird وصنف Airplane، كلاهما يحتويان على دالة fly بنفس الاسم ولكن بمحتوى مختلف. نلاحظ أننا يمكننا استخدام الدالة make_it_fly لاستدعاء دالة fly من أي كائن له هذه الدالة، سواء كان من صنف Bird أو Airplane، دون الحاجة للتحقق من النوع الصريح للكائن. هذا يُظهر كيف يمكن للتعددية الشكلية عبر التعداد أن تُسهل استخدام الكائنات المتنوعة التي تمتلك نفس الأسلوب.
التعددية الشكلية باستخدام الدوال العامة
من طرق أخرى لاستخدام التعددية الشكلية في بايثون هو عبر استخدام الدوال العامة (Generic Functions). بايثون يدعم كتابة دوال يمكنها التعامل مع مجموعة متنوعة من الأنواع (Types) بدلاً من الاقتصار على نوع معين. هذه الدوال تعتمد على الطريقة التي يتصرف بها الكائن بدلاً من نوعه الثابت.
مثال: دوال عامة للتعددية الشكلية
pythondef print_area(shape):
print(f"The area is {shape.area()}")
class Circle:
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius * self.radius
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
circle = Circle(5)
rectangle = Rectangle(4, 6)
print_area(circle) # Output: The area is 78.5
print_area(rectangle) # Output: The area is 24
في هذا المثال، تقوم دالة print_area بطباعة المساحة الخاصة بأي شكل يتم تمريره إليها، سواء كان دائرة (Circle) أو مستطيل (Rectangle). كل صنف يعرف دالة area الخاصة به، ولكن دالة print_area تعمل بشكل غير محدد لنوع الكائن، مما يتيح التعددية الشكلية.
التعددية الشكلية باستخدام الدوال المدمجة
في بايثون، العديد من الدوال المدمجة مثل len أو max تدعم التعددية الشكلية، حيث يمكن استدعاؤها على أنواع بيانات مختلفة. على سبيل المثال، دالة len يمكن استخدامها للحصول على طول الكائنات مثل السلاسل النصية (Strings) والقوائم (Lists) والمجموعات (Sets) والعديد من الأنواع الأخرى.
مثال: التعددية الشكلية مع الدوال المدمجة
pythonprint(len("Hello")) # Output: 5
print(len([1, 2, 3, 4])) # Output: 4
print(len({1, 2, 3})) # Output: 3
هنا، نلاحظ أن دالة len تعمل على عدة أنواع مختلفة من البيانات بفضل التعددية الشكلية. وهذا يظهر مرة أخرى كيف يسمح بايثون بتنفيذ العمليات على أنواع متعددة من الكائنات بطريقة مرنة وقوية.
الخلاصة
التعددية الشكلية في بايثون هي آلية قوية تسمح بكتابة كود مرن وقابل للصيانة. من خلال استخدامها في التوارث أو عبر التعداد، يمكن إنشاء برامج تتسم بالقوة والمرونة في التعامل مع أنواع متعددة من الكائنات. توفر بايثون بيئة غنية لدعم هذه الآلية، مما يسهل كتابة البرمجيات التي تتعامل مع الكائنات بشكل أكثر سلاسة وتنظيمًا. التعددية الشكلية ليست مجرد مفهوماً مجردًا، بل هي جزء لا يتجزأ من تصميم البرمجيات الحديثة التي تسعى إلى تحسين الكفاءة والأداء.

