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

السمات مقابل الوراثة

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

الآن بعد أن فهمت كيفية عمل السمات (traits)، دعنا نوضح متى نستخدم السمات مقابل الوراثة (inheritance). كلاهما يسمح بإعادة استخدام الكود، ولكنهما يخدمان أغراضاً مختلفة ولهما خصائص متميزة.

تُنشئ الوراثة علاقة "is-a". فئة Dog التي ترث من Animal تعني أن الكلب هو حيوان. ترث الفئة الابنة هوية الفئة الأب ويمكن استخدامها في أي مكان يُتوقع فيه النوع الأب.

توفر السمات (Traits) قدرة "يملك" (has-a). فعندما تستخدم فئة (class) سمة Loggable، فإنها تمتلك وظيفة التسجيل (logging) - لكنها لا تصبح مسجلاً (logger). تضيف السمات (Traits) سلوكاً دون تغيير ماهية الفئة بشكل أساسي.

<?php
// الوراثة: الكلب هو حيوان (Inheritance: Dog IS an Animal)
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// السمة (Trait): الكلب لديه قدرة التسجيل (Trait: Dog HAS logging capability)
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}

الاختلافات الرئيسية التي يجب تذكرها:

الجانبالوراثة (Inheritance)السمات (Traits)
العلاقةis-aامتلاك قدرة (has-a)
الحدأب واحد فقطيُسمح بسمات متعددة
التحقق من النوعيعمل مع instanceofلا توجد هوية نوع
الأفضل لـالعلاقات الهرميةالسلوكيات المشتركة عبر فئات غير مرتبطة

استخدم inheritance عندما تشترك classes في هوية مشتركة. استخدم traits عندما تحتاج classes غير المرتبطة إلى نفس الوظيفة دون أن تكون جزءاً من نفس شجرة العائلة.

challenge icon

التحدي

سهل

لنقم ببناء نظام مركبات يوضح متى يجب استخدام الوراثة (inheritance) مقابل السمات (traits). ستقوم بإنشاء تسلسل هرمي للمركبات التي تشترك في هوية عامة من خلال الوراثة، مع إضافة قدرات عرضية من خلال السمات.

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

  • Trackable.php — أنشئ سمة (trait) تسمى Trackable توفر إمكانية تتبع GPS. يجب أن تحتوي السمة على:
    • خاصية خاصة $location (سلسلة نصية)
    • دالة setLocation(string $location) تقوم بتخزين الموقع الحالي
    • دالة getLocation() تعيد "Location: [location]"
    تمثل هذه السمة قدرة "يحتوي على" (has-a) — يمكن لأي مركبة أن تحتوي على تتبع، لكن وجود التتبع لا يجعل الشيء مركبة.
  • Vehicle.php — أنشئ فئة أساسية Vehicle تؤسس علاقة "هو" (is-a). قم بتضمين ملف السمة. استخدم ترقية المنشئ (constructor promotion) لتعريف خاصية محمية $brand. أضف دالة describe() تعيد "Vehicle: [brand]". يجب أن تستخدم هذه الفئة سمة Trackable لأن جميع المركبات في أسطولنا ستحتوي على GPS.
  • Car.php — أنشئ فئة Car ترث من Vehicle. قم بتضمين ملف Vehicle. استخدم ترقية المنشئ لقبول العلامة التجارية وخاصية خاصة $doors (عدد صحيح). استدعِ منشئ الفئة الأب بالعلامة التجارية. قم بإعادة كتابة (Override) دالة describe() لتعيد "Car: [brand] with [doors] doors".
  • main.php — قم بتضمين ملف Car. ستتلقى ثلاثة مدخلات: اسم العلامة التجارية، عدد الأبواب، وسلسلة نصية للموقع. أنشئ مثيلاً من Car، وقم بتعيين موقعه، ثم اطبع سطرين:
    • نتيجة استدعاء describe()
    • نتيجة استدعاء getLocation()

لاحظ كيف تعمل الوراثة والسمات معاً هنا: Car هو Vehicle (الوراثة تؤسس الهوية)، بينما Vehicle لديه قدرة تتبع (السمة تضيف السلوك). يمكنك استخدام instanceof Vehicle للتحقق مما إذا كان الشيء مركبة، ولكن لا يوجد نوع "Trackable" للتحقق منه — وهذا هو الفرق الجوهري بين هذين النهجين.

ورقة مرجعية

استخدم الوراثة (inheritance) لعلاقات "is-a" و السمات (traits) لقدرات "has-a".

تُحدد الوراثة الهوية - فالفئة الابنة هي نوع من الفئة الأب ويمكن استخدامها في أي مكان يُتوقع فيه وجود النوع الأب.

تضيف السمات سلوكاً دون تغيير هوية الفئة - فالفئة تمتلك وظيفة معينة ولكنها لا تصبح ذلك الشيء.

<?php
// الوراثة: الكلب هو حيوان (Dog IS an Animal)
class Animal {
    public function breathe(): void {
        echo "Breathing";
    }
}

class Dog extends Animal {
    public function bark(): void {
        echo "Woof!";
    }
}

// السمات: القطة لديها قدرة التسجيل (Cat HAS logging capability)
trait Loggable {
    public function log(string $msg): void {
        echo "Log: $msg";
    }
}

class Cat extends Animal {
    use Loggable;
}
الجانبالوراثةالسمات
العلاقةis-aقدرة has-a
الحدأب واحد فقطيُسمح بسمات متعددة
التحقق من النوعيعمل مع instanceofلا توجد هوية للنوع
الأفضل لـالعلاقات الهرميةالسلوكيات المشتركة عبر فئات غير مرتبطة

استخدم الوراثة للعلاقات الهرمية حيث تشترك الفئات في هوية مشتركة. استخدم السمات للسلوكيات المشتركة عبر فئات غير مرتبطة.

جرّب بنفسك

<?php
// الملف الرئيسي - إنشاء واختبار مثيل السيارة (Car)

// TODO: تضمين ملف Car.php

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

// TODO: إنشاء مثيل للسيارة (Car) مع العلامة التجارية والأبواب

// TODO: تعيين موقع السيارة

// TODO: طباعة نتيجة describe()

// TODO: طباعة نتيجة getLocation()
?>
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming