مقدمة إلى Mixins
جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 50 من 110.
لقد تعلمت أن Dart تسمح فقط بتوسيع فئة (class) واحدة، وبينما يمكنك تنفيذ واجهات (interfaces) متعددة، يجب عليك كتابة الكود بالكامل بنفسك. ولكن ماذا لو كنت تريد مشاركة كود التنفيذ الفعلي عبر فئات متعددة غير مرتبطة؟ هنا يأتي دور الـ mixins.
الـ mixin هو وسيلة لإعادة استخدام الكود في تسلسلات هرمية متعددة للأصناف (class hierarchies). فكر فيه كحزمة من الدوال (methods) والخصائص (properties) التي يمكنك "دمجها" في أي صنف (class)، مما يمنحه قدرات جديدة دون استخدام الوراثة (inheritance).
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}
void main() {
var duck = Duck();
duck.quack();
duck.swim(); // من الـ mixin
var fish = Fish();
fish.swim(); // نفس التنفيذ، فئة مختلفة
}لاحظ الكلمة المفتاحية with - هذه هي الطريقة التي تطبق بها mixin على class. على عكس implements، لست بحاجة إلى كتابة الـ method بنفسك. يوفر الـ mixin الكود الفعلي، وتكتسب الـ class الخاصة بك تلك الوظيفة تلقائيًا.
تحل الـ Mixins مشكلة حقيقية: Duck و Fish غير مرتبطين من خلال الوراثة، ومع ذلك كلاهما يحتاج إلى سلوك السباحة. باستخدام الـ mixins، يمكنك كتابة الكود مرة واحدة ومشاركته أينما دعت الحاجة.
التحدي
سهللنقم ببناء نظام للآلات الموسيقية يوضح كيف تسمح لك الـ mixins بمشاركة السلوك عبر فئات (classes) غير مرتبطة. ستقوم بإنشاء mixin يوفر وظيفة الضبط (tuning)، ثم تطبقه على آلات مختلفة لا ترتبط ببعضها عبر الوراثة.
ستقوم بتنظيم الكود الخاص بك في ملفين:
instruments.dart: قم بتعريف الـ mixin وفئات الآلات هنا:- الـ mixin باسم
Tunableمع طريقة (method) باسمtune()تطبع'Tuning the instrument...'وطريقة باسمcheckTuning()تطبع'Tuning is perfect!' - فئة
Guitarتستخدم الـ mixin المسمىTunable. أضف خاصيةString brandمع منشئ (constructor). قم بتضمين طريقةstrum()تطبع'$brand guitar strumming chords' - فئة
Pianoتستخدم أيضاً الـ mixin المسمىTunable. أضف خاصيةint keysمع منشئ. قم بتضمين طريقةplay()تطبع'Playing $keys-key piano'
- الـ mixin باسم
main.dart: قم باستيراد ملف الآلات ووضح كيف تكتسب كلتا الآلتين غير المرتبطتين قدرات الضبط من نفس الـ mixin:- قم بإنشاء
Guitarبماركة'Fender' - قم بإنشاء
Pianoبـ88مفتاحاً - بالنسبة للجيتار: استدعِ
tune()، ثمstrum()، ثمcheckTuning() - اطبع سطراً فارغاً
- بالنسبة للبيانو: استدعِ
tune()، ثمplay()، thencheckTuning()
- قم بإنشاء
لاحظ كيف أن Guitar و Piano آلتان مختلفتان تماماً ولا توجد بينهما علاقة وراثة، ومع ذلك تكتسب كلتاهما نفس طرق الضبط تماماً من الـ mixin المسمى Tunable. أنت تكتب كود الضبط مرة واحدة، ويمكن لكلتا الفئتين استخدامه باستخدام الكلمة المفتاحية with.
المخرجات المتوقعة:
Tuning the instrument...
Fender guitar strumming chords
Tuning is perfect!
Tuning the instrument...
Playing 88-key piano
Tuning is perfect!ورقة مرجعية
الـ mixin هو وسيلة لإعادة استخدام الكود عبر فئات (classes) متعددة غير مرتبطة دون استخدام الوراثة (inheritance). إنه عبارة عن حزمة من الدوال (methods) والخصائص (properties) التي يمكنك "دمجها" في أي فئة.
قم بتعريف mixin باستخدام الكلمة المفتاحية mixin:
mixin Swimming {
void swim() {
print('Swimming through the water');
}
}قم بتطبيق mixin على فئة باستخدام الكلمة المفتاحية with:
class Duck with Swimming {
void quack() {
print('Quack!');
}
}
class Fish with Swimming {
void blowBubbles() {
print('Blub blub');
}
}على عكس implements، لست بحاجة إلى كتابة تنفيذ الدالة بنفسك - حيث يوفر الـ mixin الكود الفعلي، وتكتسب الفئة الخاصة بك تلك الوظيفة تلقائيًا.
يمكن لكل من Duck و Fish الآن استخدام الدالة swim() على الرغم من أنهما غير مرتبطين عبر الوراثة:
var duck = Duck();
duck.swim(); // من الـ mixin
var fish = Fish();
fish.swim(); // نفس التنفيذ، فئة مختلفةجرّب بنفسك
import 'instruments.dart';
void main() {
// TODO: Fender بماركة Guitar قم بإنشاء
// TODO: يحتوي على 88 مفتاحاً Piano قم بإنشاء
// TODO: ثم ()checkTuning ثم ()strum ثم ()tune استدعِ :guitar بالنسبة لـ
// TODO: قم بطباعة سطر فارغ
// TODO: ثم ()checkTuning ثم ()play ثم ()tune استدعِ :piano بالنسبة لـ
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع