Mixin مقابل الوراثة (Inheritance)
جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 54 من 110.
بعد أن تعلمت الآن كيفية عمل الـ mixins، دعنا نوضح متى نستخدمها بدلاً من الوراثة (inheritance). يكمن الفرق الجوهري في العلاقة التي يعبران عنها.
يمثل التوريث علاقة "is-a". الـ Dog هو Animal. الفئة الفرعية هي نسخة متخصصة من الفئة الأب، ويمكنك فقط توسيع فئة واحدة.
الميكسنز (Mixins)، من ناحية أخرى، تمثل علاقة "يمكنه القيام بـ" (can-do). الـ Dog يمكنه السباحة، ولكن السباحة ليست هي ما يحدد الكلب.
// الوراثة: الكلب هو حيوان (Dog IS an Animal)
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: الكلب يستطيع السباحة (لكنه لا يُعرّف من خلال السباحة)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}استخدم الوراثة عندما تتشارك الأصناف هوية أساسية وتحتاج إلى constructors في الصنف الأب. استخدم الـ mixins عندما تريد إضافة قدرات إلى أصناف لا تشترك في سلف مشترك.
| الميزة | الوراثة (Inheritance) | Mixin |
|---|---|---|
| العلاقة | is-a (هو نوع من) | can-do (يمكنه القيام بـ) |
| القيود | أب واحد فقط | عدة Mixins |
| الدوال البنائية (Constructors) | مسموح بها | غير مسموح بها |
| حالة الاستخدام | التخصيص (Specialization) | سلوك مشترك |
الجزء الأفضل؟ يمكنك الجمع بين كليهما - توسيع فئة واحدة ودمج قدرات متعددة، مما يمنح فئاتك الميزات التي تحتاجها بالضبط.
التحدي
سهللنقم ببناء نظام عمال يوضح متى يتم استخدام الوراثة (inheritance) مقابل الـ mixins. ستقوم بإنشاء فئة أساسية لعلاقة "is-a" (هو عبارة عن) و mixins لإمكانيات "can-do" (يمكنه القيام بـ)، ثم تجمعهما معاً لإظهار كيف يعمل كلا النهجين معاً.
ستقوم بتنظيم الكود الخاص بك في ثلاثة ملفات:
worker.dart: حدد الفئة الأساسية التي تثبت الهوية الجوهرية لجميع العمال:- فئة
Workerمع خصائصString nameوString department. قم بتضمين منشئ (constructor) يأخذ كلتا القيمتين. أضف دالةintroduce()تطبع[name] works in [department]
- فئة
skills.dart: حدد الـ mixins التي تمثل القدرات التي يمكن للعمال امتلاكها (علاقات "can-do"):- mixin باسم
CanCodeمع دالةwriteCode()تطبعWriting code... - mixin باسم
CanDesignمع دالةcreateDesign()تطبعCreating design... - mixin باسم
CanManageمع دالةleadTeam()تطبعLeading the team...
- mixin باسم
main.dart: قم باستيراد كلا الملفين وإنشاء أنواع عمال متخصصة تجمع بين الوراثة والـ mixins:- فئة
Developerترث منWorkerوتستخدم mixin الـCanCode - فئة
TechLeadترث منWorkerوتستخدم كلا الـ mixins:CanCodeوCanManage - أنشئ
Developerباسم'Alice'في قسم'Engineering' - أنشئ
TechLeadباسم'Bob'في قسم'Engineering' - بالنسبة لـ Alice: استدعِ
introduce()ثمwriteCode() - اطبع سطراً فارغاً
- بالنسبة لـ Bob: استدعِ
introduce()، ثمwriteCode()، ثمleadTeam()
- فئة
لاحظ كيف أن كلاً من Developer و TechLead هما عمال (وراثة)، لكنهما يستطيعان القيام بأشياء مختلفة (mixins). يجمع TechLead بين قدرات متعددة دون الحاجة إلى الوراثة المتعددة.
المخرجات المتوقعة:
Alice works in Engineering
Writing code...
Bob works in Engineering
Writing code...
Leading the team...ورقة مرجعية
تمثل الوراثة (Inheritance) علاقة "هو-نوع-من" ("is-a") (حيث تكون الفئة الفرعية نسخة متخصصة من الفئة الأب)، بينما تمثل الـ mixins علاقة "يمكنه-القيام-بـ" ("can-do") (إضافة قدرات دون تعريف الهوية).
// الوراثة: الكلب هو حيوان (Dog IS an Animal)
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// Mixin: الكلب يمكنه السباحة (Dog CAN swim)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}| الميزة | الوراثة (Inheritance) | الـ Mixin |
|---|---|---|
| العلاقة | هو-نوع-من (is-a) | يمكنه-القيام-بـ (can-do) |
| القيود | أب واحد فقط | عدة mixins |
| الدوال البنائية (Constructors) | مسموح بها | غير مسموح بها |
| حالة الاستخدام | التخصص (Specialization) | سلوك مشترك (Shared behavior) |
يمكنك الجمع بين كلا النهجين - توسيع فئة واحدة ودمج قدرات متعددة:
class TechLead extends Worker with CanCode, CanManage {
TechLead(String name, String department) : super(name, department);
}جرّب بنفسك
import 'worker.dart';
import 'skills.dart';
// TODO: قم بإنشاء فئة Developer ترث من Worker وتستخدم mixin من نوع CanCode
// TODO: قم بإنشاء فئة TechLead ترث من Worker وتستخدم كلاً من mixins من نوع CanCode و CanManage
void main() {
// TODO: قم بإنشاء Developer باسم 'Alice' في قسم 'Engineering'
// TODO: قم باستدعاء introduce() ثم writeCode() لـ Alice
// TODO: قم بطباعة سطر فارغ
// TODO: قم بإنشاء TechLead باسم 'Bob' في قسم 'Engineering'
// TODO: قم باستدعاء introduce() و writeCode() ثم leadTeam() لـ Bob
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات الـ OOP
الملفات الخارجيةالمكتبات والـ Importsمقدمة في الـ OOPالـ Classes مقابل الـ Objectsالكلمة المفتاحية thisالـ Methodsمتغيرات الـ Instanceأساسيات الـ Constructorمراجعة - آلة حاسبة بسيطة4أمان الـ Null
مقدمة في أمان الـ NullNullable مقابل Non-Nullableعاملا الـ ? و !الكلمة المفتاحية Late وأمان الـ Nullالعوامل المدركة للـ Nullأمان الـ Null في الـ Classesمراجعة - نظام ملف تعريف المستخدم7الفئات المجردة والواجهات
الفئات المجردةالدوال المجردةالواجهات في Dartالواجهات الضمنيةالتنفيذ مقابل التوسيعالواجهات المتعددةمراجعة - حاسبة الأشكال10المجموعات والأنماط العامة
نظرة عامة على List و Set و Mapالمجموعات آمنة النوعالفئات العامةالدوال العامةقيود الأنماط العامةIterable و Iteratorملخص - التخزين العام13مفاهيم OOP المتقدمة
التركيب مقابل الوراثة (Composition vs Inheritance)دوال التوسعة (Extension Methods)الأصناف القابلة للاستدعاء (Callable Classes)الأصناف المختومة (Sealed Classes - Dart 3)السجلات (Records - Dart 3)الأنماط والمطابقة (Patterns & Matching - 3.0)التعدادات مع الدوال (Enums with Methods)2المنشئات في Dart
المنشئ الافتراضيالمنشئات المسماةقوائم التهيئةالمنشئات الثابتةالمنشئات المصنعيةالمنشئات الموجهةملخص - بناء الأشكال5التغليف (Encapsulation)
الأعضاء العامة مقابل الخاصةاتفاقية البادئة _الخصوصية على مستوى المكتبةتعمق في Getters و Settersإخفاء المعلوماتمراجعة - سجلات الطلاب8Mixins
مقدمة إلى Mixinsإنشاء Mixinsاستخدام Mixins متعددةالكلمة المفتاحية on في MixinsMixin مقابل الوراثة (Inheritance)Mixin مقابل الواجهة (Interface)مراجعة - نظام الحيوانات (Animal System)3خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticحقول Final و Constمتغيرات Lateالـ Static Methods والحقولدوال الـ Getters والـ Settersمراجعة - مدير الحساب البنكي6الوراثة
أساسيات الوراثةالكلمة المفتاحية superإعادة تعريف الدوال (Method Overriding)الوسم @overrideالكلمة المفتاحية final Classالدوال البانية والوراثةمراجعة - هيكلية الموظفين9تعدد الأشكال
أساسيات تعدد الأشكالتعدد الأشكال عبر الـ Interfacesالتحقق من النوع أثناء التشغيلالمعاملات is و asالكلمة المفتاحية Covariantملخص - معالج الدفع12البرمجة الكائنية غير المتزامنة (Async OOP)
Futures و async/awaitأساسيات الـ Streamsمتحكمات الـ Streamsالـ Constructors غير المتزامنةالعمليات غير المتزامنة في دوال الكلاسمراجعة - جالب البيانات (Data Fetcher)15أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع