مراجعة الفئات المجردة
مراجعة الفئات المجردة
أنت تعرف مسبقًا كيف تمدّ فئةً وتتجاوز دوالّها. في هذا الدرس نتوقّف ونمعن النظر في الفئات المجردة من زاوية جديدة — لا بوصفها ميزةً نحوية فحسب، بل أداةً تصميمية. بنهاية الدرس ستعرف متى تكون الفئة المجردة الخيار الصواب، وكيف تمزج الدوال المجردة والملموسة بفعالية، وما الفخاخ التي ينبغي تجنّبها.
ما الذي تعنيه الكلمة المفتاحية abstract فعلًا
وضع abstract على فئة يفعل شيئين في آنٍ واحد:
- يحظر الإنشاء المباشر — لا يمكن لأحد استدعاء
new Shape()إذا كانتShapeمجردة. - يتيح الدوال المجردة — تصريحات دوال بلا جسم تُلزم الفئات الفرعية بتنفيذها.
هذان الحكمان يعملان معًا: لا يمكنك إنشاء نسخة من فئة تحتوي على دوال غير منفَّذة، فالمُصرِّف يفرض العقد تلقائيًا.
لاحظ أن describe() منفَّذة بالكامل في الفئة المجردة وتستدعي area(). في وقت التشغيل تُوجَّه الاستدعاء إلى Circle.area(). هذا هو نمط Template Method في أبسط صوره: الفئة الأساسية ترسم هيكل الخوارزمية، وتملأ الفئات الفرعية الفراغات.
الدوال المجردة مقابل الملموسة — اختيار ما تُوفّره
كل دالة في فئة مجردة إما مجردة (مؤجَّلة) أو ملموسة (مشتركة). القاعدة الإرشادية:
- اجعل الدالة مجردة عندما تحتاج كل فئة فرعية فعلًا إلى تنفيذ مختلف ولا يوجد سلوك افتراضي منطقي.
- اجعل الدالة ملموسة عندما تشترك معظم الفئات الفرعية في نفس السلوك، أو عندما تريد بناء منطق قابل لإعادة الاستخدام يستدعي الأجزاء المجردة.
final مع الدوال القالبية: تعليم الدالة المُنسِّقة بـ final يمنع الفئات الفرعية من كسر سير العمل عن طريق الخطأ. دوال الخطّاف المجردة هي ما تُخصّصه الفئات الفرعية — أما الهيكل فيبقى ثابتًا.
التنفيذات الجزئية وحقن المُنشئ
يمكن للفئات المجردة امتلاك مُنشئات وحقول وأي قدر من الكود الملموس. هذه ميزة رئيسية على الواجهات (التي ندرسها في الدرس التالي): يمكنك تخزين الحالة وإعادة استخدام منطق التهيئة.
protected لمُنشئات الفئة المجردة عندما ينبغي للفئة أن لا تُبنى إلا من خلال الفئات الفرعية. public يعمل أيضًا (المُصرِّف يمنع الإنشاء المباشر على أي حال)، لكن protected يُعبّر عن النية بصورة أوضح.
متى تكون الفئة المجردة الأداة المناسبة
اطرح على نفسك هذه الأسئلة:
- هل توجد علاقة "is-a" حقيقية؟ الكلب حيوان؛ الفئة المجردة تُجسّد هذا النوع الأب.
- هل تشترك الفئات الفرعية في حالة فعلية؟ إذا احتاجت كل فئة فرعية إلى حقل
name، ضعه في الفئة المجردة. - هل يوجد هيكل خوارزمية مشترك؟ الدوال القالبية تتألّق عندما تكون الخطوات متشابهة لكن بعضها يتفاوت.
- هل يكفي الوراثة الأحادية؟ الفئة يمكنها مدّ أب واحد فقط. إذا احتجت تأليف أنواع متعددة، ستحتاج إلى واجهات (الدرس التالي).
ضمانات المُصرِّف
يفرض مُصرِّف Java العقد المجرد في كل خطوة:
- محاولة إنشاء نسخة من فئة مجردة هي خطأ في وقت التصريف، ليس في وقت التشغيل.
- فئة فرعية لا تنفّذ جميع الدوال المجردة يجب هي نفسها أن تُعلَن
abstract. - يمكنك الاحتفاظ بمرجع من نوع
ShapeأوAnimal— تعدّدية الأشكال تعمل بصورة طبيعية؛ المحظور فقط هو الإنشاء المباشر.
الخلاصة
الفئة المجردة نوعٌ منفَّذ جزئيًا يُلزم الفئات الفرعية باستكمال العقد مع مشاركة الكود القابل لإعادة الاستخدام. استخدمها عندما يكون لديك تسلسل هرمي حقيقي مع حالة أو سلوك مشترك، وعندما يظهر نمط الدالة القالبية بصورة طبيعية. في الدرس التالي نُقدّم الواجهات — آليةً مكمّلة (وأكثر شيوعًا في الغالب) للتعبير عن العقود دون وراثة.