الأصناف والدوال المجردة
جزء من قسم البرمجة كائنية التوجه في رحلة Python على Coddy. الدرس 25 من 64.
الفئات المجرّدة هي فئات لا يمكن إنشاء كائنات منها مباشرةً، وتحتوي على أساليب مجرّدة يجب أن تنفّذها الفئات الفرعية.
تخيّل الأمر كنموذج: الفئة المجرّدة أشبه بنموذج إلزامي، بعض حقوله مطلوبة (الأساليب المجرّدة) وبعضها اختياري (الأساليب الفعلية). لا يمكنك إرسال النموذج نفسه؛ بل يجب أن تملأ جميع الحقول المطلوبة أولًا. وبالمثل، لا يمكنك إنشاء كائنات من فئة مجرّدة حتى تُنفَّذ جميع الأساليب المجرّدة في فئة فرعية.
استورد وحدة abc لإنشاء فئات مجرّدة:
from abc import ABC, abstractmethodأنشئ فئة مجرّدة تحتوي على أساليب مجرّدة:
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # دالة مُنفَّذة (لها تنفيذ)تُحدِّد أداة التزيين @abstractmethod الطرق التي يجب أن تنفّذها الفئات الفرعية — فهذه هي «الحقول المطلوبة» في نموذجك. أما الطرق العادية مثل describe()، فيمكن أن يكون لها تنفيذ وتُورَث كما هي — فهذه هي «الحقول المعبأة مسبقًا».
لماذا نستخدم الأصناف المجرّدة؟ إنها تفرض عقدًا. إذا أنشأت صنفًا باسم Shape، فأنت تقول: «يجب أن يكون كل شكل قادرًا على حساب مساحته ومحيطه». وهذا يمنع الأخطاء التي قد تقع فيها إذا نسيت تنفيذ طرائق أساسية.
حاول إنشاء مثيل من الصنف المجرّد:
# سيؤدي هذا إلى حدوث خطأ:
# shape = Shape() # TypeError: لا يمكن إنشاء مثيل من فئة مجردةهذا الخطأ مقصود — إنه أشبه بمحاولة إرسال نموذج فارغ. تقول Python: «لم تملأ الحقول المطلوبة (طريقتَي المساحة والمحيط) بعد!»
أنشئ صنفًا فرعيًا ملموسًا ينفّذ جميع الأساليب المجرّدة:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radiusالآن «أكملنا جميع الحقول المطلوبة» — لقد نفّذنا كلًا من area() وperimeter(). أصبح الصنف Circle الآن صنفًا ملموسًا مكتملًا يمكن إنشاء كائن منه.
والآن يمكنك إنشاء مثيلات من الفئة الملموسة:
circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe()) # طريقة فعلية موروثةأنشئ صنفًا فرعيًا ملموسًا آخر:
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())الناتج:
78.5
31.400000000000002
This is a shape
24
20تحدّد الفئات المجرّدة عقدًا يجب أن تلتزم به الفئات الفرعية. استخدم ABC و@abstractmethod لإنشاء فئات مجرّدة. يجب على الفئات الفرعية تنفيذ جميع الأساليب المجرّدة، وإلا فستكون مجرّدة هي الأخرى. وهذا يضمن الاتساق ويمنع التطبيقات غير المكتملة.
التحدي
متوسطفي هذا التحدي، ستنفّذ نظامًا لمعالجة المدفوعات.
عليك إكمال التنفيذ في هذه الملفات:
paymentmethod.py- الفئة الأساسية المجرّدة مع منطق التحققcreditcard.py- تنفيذ الدفع ببطاقة ائتمانpaypal.py- تنفيذ الدفع عبر PayPal
اتبع تعليقات TODO في كل ملف لتنفيذ الوظائف المطلوبة. سترشدك التعليقات خطوة بخطوة إلى إنشاء الأساليب المجرّدة، وتنفيذ الفئات الفرعية الملموسة، وإعداد علاقات الاستيراد المناسبة بين الملفات.
يحتوي الملف driver.py على حالات اختبار ستتحقق من عمل تنفيذك على النحو الصحيح، وذلك بمعالجة سيناريوهات دفع مختلفة وعرض التفاصيل المناسبة لكل طريقة دفع.
جرّب بنفسك
from creditcard import CreditCard
from paypal import PayPal
# اختبر التنفيذات - لا تعدّل رمز الاختبار هذا
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")
# عالِج المدفوعات الصالحة
if cc.validate(100):
print(cc.process_payment(100))
print(cc.payment_details())
if pp.validate(200):
print(pp.process_payment(200))
print(pp.payment_details())
# جرّب مبلغًا غير صالح
if not pp.validate(0):
print("Invalid payment amount")
# سيؤدي هذا إلى حدوث خطأ إذا أُزيلت عنه علامة التعليق:
# pm = PaymentMethod() # لا يمكن إنشاء مثيل من فئة مجردةيتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات البرمجة كائنية التوجّه (OOP)
مقدمة إلى OOPالملفات الخارجيةالصفوف مقابل الكائناتالمعامل selfالأساليبالسماتالأسلوب الباني (__init__)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةدالة ()superإعادة تعريف الدوال (Method Overriding)الوراثة المتعددةترتيب استدعاء الدوال (Method Resolution Order)مراجعة - هيكلية الموظفين5تعدد الأشكال
مراجعة إعادة تعريف الدوالمفهوم Duck Typingالأصناف والدوال المجردةتصميم الواجهاتملخص - حاسبة الأشكالتدرّب بنفسك: مترجم Python عبر الإنترنت