Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الواجهة مقابل الـ Abstract Class

جزء من قسم Object Oriented Programming في رحلة PHP على Coddy — الدرس 30 من 91.

الآن بعد أن تعلمت كلًا من الواجهات (interfaces) والفئات المجردة (abstract classes)، دعنا نوضح متى نستخدم كلًا منهما. فبينما قد يبدوان متشابهين، إلا أنهما يخدمان أغراضًا مختلفة ولهما قدرات متميزة.

الميزة الواجهة (Interface) الفئة المجردة (Abstract Class)
الدوال (Methods) تواقيع الدوال فقط كلا النوعين من الدوال (المجردة والملموسة)
الخصائص (Properties) الثوابت فقط يمكن أن تحتوي على خصائص
الوراثة المتعددة يمكن للفئة تنفيذ واجهات متعددة يمكن للفئة وراثة فئة واحدة فقط
المنشئ (Constructor) غير مسموح به يمكن أن تحتوي على منشئ

استخدم interface عندما تريد تعريف عقد يمكن للأصناف غير المرتبطة الوفاء به. على سبيل المثال، قد يقوم كل من Printer و Logger بتنفيذ واجهة Writable، على الرغم من أنهما لا يشتركان في أي سلف مشترك.

استخدم فئة مجردة (abstract class) عندما يكون لديك فئات ذات صلة تشترك في كود برمجي مشترك. إذا كانت فئتا Dog و Cat تحتاجان إلى نفس تنفيذ الدالة eat()، فإن فئة Animal مجردة (abstract) تتيح لك كتابة هذا الكود مرة واحدة.

يمكنك أيضاً الجمع بين كلا النهجين. حيث يمكن لفئة (class) أن ترث من فئة مجردة (abstract class) مع تنفيذ واجهات (interfaces) متعددة في آن واحد:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

نقطة رئيسية: اختر الواجهات (interfaces) لتحديد القدرات عبر الفئات (classes) غير المرتبطة. اختر الفئات المجردة (abstract classes) عندما تحتاج إلى مشاركة الكود بين الفئات ذات الصلة.

challenge icon

التحدي

سهل

لنقم ببناء نظام مركبات يوضح متى يجب استخدام فئة مجردة (abstract class) مقابل واجهة (interface) — وكيفية الجمع بين كلا النهجين بفعالية.

ستقوم بإنشاء نظام تشترك فيه المركبات في خصائص عامة من خلال الوراثة، ولكن يمكنها أيضاً اكتساب قدرات إضافية من خلال الواجهات. هذا يحاكي قرارات التصميم في العالم الحقيقي: السيارة "هي" مركبة (وراثة)، ولكن لديها أيضاً "القدرة" على أن تكون قابلة للتزود بالوقود (واجهة).

قم بتنظيم الكود الخاص بك عبر أربعة ملفات:

  • Refuelable.php — قم بتعريف واجهة Refuelable مع توقيع طريقة واحدة: refuel($amount). يمكن تطبيق هذه القدرة على أي فئة تحتاج إلى التزود بالوقود، بغض النظر عن تسلسل الوراثة الخاص بها.
  • Vehicle.php — قم بتعريف فئة مجردة Vehicle توفر وظائف مشتركة لجميع المركبات. يجب أن تحتوي على خاصية محمية $brand وخاصية محمية $fuelLevel (تبدأ بـ 0). يقبل المنشئ (constructor) اسم العلامة التجارية. قم بتضمين طريقة ملموسة getBrand() تعيد العلامة التجارية، وطريقة ملموسة getFuelLevel() تعيد مستوى الوقود الحالي، وطريقة مجردة drive() يجب على الفئات التابعة تنفيذها.
  • Car.php — قم بإنشاء فئة Car ترث من Vehicle وتنفذ Refuelable. قم بتضمين كلا الملفين المطلوبين في الأعلى. يقبل المنشئ العلامة التجارية ويمررها إلى منشئ الفئة الأب. قم بتنفيذ drive() لتعيد "[brand] car is driving". قم بتنفيذ refuel($amount) لإضافة الكمية إلى مستوى الوقود وإعادة "[brand] refueled to [fuelLevel] liters".
  • main.php — قم بتضمين ملف Car. ستتلقى مدخلين: اسم العلامة التجارية وكمية الوقود (قم بتحويلها إلى عدد صحيح). قم بإنشاء Car بالعلامة التجارية. اطبع نتيجة drive() في السطر الأول، ثم اطبع نتيجة refuel() مع كمية الوقود في السطر الثاني.

يوضح هذا التحدي التمييز الرئيسي: الفئة المجردة Vehicle تشارك الكود وتؤسس علاقة "is-a" (هي نوع من)، بينما تضيف واجهة Refuelable قدرة يمكن تطبيقها على فئات أخرى غير مرتبطة (مثل المولد أو القارب) دون مطالبتها بأن تكون مركبات.

ورقة مرجعية

تخدم الواجهات (Interfaces) والفئات المجردة (Abstract classes) أغراضاً مختلفة:

الميزة الواجهة (Interface) الفئة المجردة (Abstract Class)
الأساليب (Methods) تواقيع الأساليب فقط كل من الأساليب المجردة والملموسة
الخصائص (Properties) الثوابت فقط يمكن أن تحتوي على خصائص
الوراثة المتعددة يمكن للفئة تنفيذ العديد منها يمكن للفئة توسيع واحدة فقط
المنشئ (Constructor) غير مسموح به يمكن أن تحتوي على منشئ

استخدم الواجهة (interface) لتحديد عقد للفئات غير المرتبطة. استخدم الفئة المجردة (abstract class) لمشاركة الكود المشترك بين الفئات المرتبطة.

يمكن للفئة توسيع فئة مجردة مع تنفيذ واجهات متعددة في نفس الوقت:

<?php
abstract class Animal {
    protected $name;
    
    public function eat() {
        return $this->name . " is eating";
    }
}

interface Swimmable {
    public function swim();
}

class Duck extends Animal implements Swimmable {
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function swim() {
        return $this->name . " is swimming";
    }
}

جرّب بنفسك

<?php
require_once 'Car.php';

// قراءة المدخلات
$brand = trim(fgets(STDIN));
$fuelAmount = intval(trim(fgets(STDIN)));

// TODO: إنشاء كائن Car مع العلامة التجارية (brand)

// TODO: طباعة نتيجة drive() في السطر الأول

// TODO: طباعة نتيجة refuel() مع كمية الوقود في السطر الثاني
?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming