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

مقدمة إلى 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، يمكنك كتابة الكود مرة واحدة ومشاركته أينما دعت الحاجة.

challenge icon

التحدي

سهل

لنقم ببناء نظام للآلات الموسيقية يوضح كيف تسمح لك الـ 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'
  • main.dart: قم باستيراد ملف الآلات ووضح كيف تكتسب كلتا الآلتين غير المرتبطتين قدرات الضبط من نفس الـ mixin:
    • قم بإنشاء Guitar بماركة 'Fender'
    • قم بإنشاء Piano بـ 88 مفتاحاً
    • بالنسبة للجيتار: استدعِ tune()، ثم strum()، ثم checkTuning()
    • اطبع سطراً فارغاً
    • بالنسبة للبيانو: استدعِ tune()، ثم play()، then checkTuning()

لاحظ كيف أن 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 بالنسبة لـ
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming