يُصرَّح بالصنف المجرد في PHP بـ abstract class Name ولا يمكن إنشاؤه بـ new. إنه أساس لأصناف أخرى: يمكن أن تكون له خصائص وباني وتوابع مكتملة، إضافة إلى توابع abstract دون جسم، يجب على كل صنف ابن تنفيذها.
تُكتب describe() مرة واحدة في Shape وتستدعي area()، التي يوفرها كل ابن. ويضمن الصنف المجرد وجود التابع، فتستطيع describe() الاعتماد عليه.
لا يمكنك إنشاء صنف مجرد بـ new
الصنف المجرد ناقص عمدًا: ليس لـ Shape::area() جسم، فلن يجد كائن Shape عادي شيئًا ينفّذه. ترفض PHP إنشاء واحد وترمي Error:
التوابع المجردة: القواعد
للتابع المجرد توقيع وفاصلة منقوطة بدل الجسم. يجب على كل ابن تنفيذه بتوقيع متوافق وبرؤية مماثلة أو أوسع: يمكن أن يصبح التابع abstract protected في الابن protected أو public، لكن ليس private أبدًا. والصنف الذي فيه ولو تابع مجرد واحد يجب أن يُصرَّح به هو نفسه مجردًا.
الابن الذي يتخطى تابعًا مجردًا يوقف السكربت قبل أن يعمل أي جزء منه، ما لم يُصرَّح بالابن أيضًا مجردًا ويترك التابع لأبنائه:
PHP Fatal error: Class Square contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Shape::area) in /home/index.php on line 3
نمط تابع القالب
أشهر سبب لكتابة صنف مجرد: تسلسل ثابت من الخطوات تختلف فيه خطوات قليلة. يملك الصنف الأساسي التسلسل في تابع final، ويملأ الأبناء الخطوات. هنا يعمل التقرير نفسه نصًا عاديًا وجدول HTML:
شغّله فيعرض تبويب Page جدول HTML فوق النسخة النصية العادية. لـ open() وclose() أجسام افتراضية، فلا يعيد تعريفهما إلا HtmlReport؛ أما row() فمجرد لأنه لا توجد قيمة افتراضية معقولة. وجعل render() من نوع final يمنع الابن من تغيير ترتيب الخطوات.
الصنف المجرد يستطيع تنفيذ واجهة
يمكن للصنف المجرد أن يصرّح بـ implements ويترك بعض توابع الواجهة لأبنائه. وهذه الطريقة المعتادة لاقتران واجهة (النوع) بصنف أساسي (الشيفرة المشتركة):
تلمّح الشيفرة بالواجهة Cache، لذا يستطيع صنف لا يمكنه وراثة BaseCache (لأنه يرث شيئًا آخر أصلًا) تنفيذ Cache مباشرة.
متى تستخدم صنفًا مجردًا ومتى لا
استخدم الصنف المجرد عندما تتشارك أصناف العائلة شيفرة حقيقية: خصائص، وبانيًا، وتوابع متماثلة لها كلها. وإذا كان الأساس لن يحتوي إلا توابع مجردة، فهو واجهة متنكرة، والواجهة الخيار الأفضل لأن الصنف يستطيع تنفيذ واجهات كثيرة لكنه لا يرث إلا صنفًا واحدًا. وإذا كنت تريد فقط مشاركة بعض التوابع المساعدة بين أصناف غير مترابطة، فاستخدم سمة بدل إجبارها تحت أب واحد.
اختبار سريع قبل كتابة abstract class: هل سيكون كل ابن فعلًا نوعًا من الأساس (Circle هو Shape)؟ إذا كانت الإجابة الصادقة «يستطيع فعل هذا» لا «هو واحد من هذه»، فاكتب واجهة.
الأسئلة الشائعة
ما هو الصنف المجرد في PHP؟
صنف يُصرَّح به بـ abstract class Name ولا يمكن إنشاؤه بـ new. إنه أساس لأصناف أخرى: يمكن أن يحتوي خصائص وبانيًا وتوابع عادية، ويمكنه التصريح بتوابع abstract يجب على كل صنف ابن تنفيذها.
ما هو التابع المجرد في PHP؟
تابع يُصرَّح به بـ abstract ودون جسم: abstract protected function render(array $rows): string;. الصنف الذي يحتوي واحدًا منها يجب أن يُصرَّح به هو نفسه abstract، وكل صنف ابن غير مجرد يجب أن يعرّف تابعًا بتوقيع متوافق.
هل يمكن أن يكون للصنف المجرد باني في PHP؟
نعم. لا يمكنك استدعاء new على الصنف المجرد، لكن بانيه يعمل عند إنشاء صنف ابن، إما تلقائيًا (إذا لم يكن للابن باني) أو عبر parent::__construct(...).
هل يمكن إنشاء كائن من صنف مجرد في PHP؟
لا. ترمي new Shape() على صنف مجرد الخطأ Error: Cannot instantiate abstract class Shape. أنشئ كائنًا من صنف ابن ملموس بدلًا من ذلك، مثل new Circle(2).
متى أستخدم صنفًا مجردًا في PHP؟
عندما تتشارك عدة أصناف مترابطة شيفرة حقيقية (خصائص، باني، توابع مشتركة) وتختلف في خطوات قليلة. ضع الشيفرة المشتركة في الصنف المجرد وصرّح بالخطوات المختلفة مجردةً. وإذا لم توجد شيفرة مشتركة وكنت تحتاج إلى عقد فقط، فاستخدم واجهة.