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

أساسيات تعدد الأشكال

جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 57 من 110.

تعدد الأشكال (Polymorphism) يعني "أشكالاً متعددة" - وهي القدرة على التعامل مع كائنات من فئات (classes) مختلفة من خلال واجهة مشتركة. عندما يكون لديك مرجع لفئة أب (parent class reference)، يمكنه الإشارة إلى أي كائن من فئة ابن (child class object)، ويتم استدعاء الطريقة (method) الصحيحة بناءً على نوع الكائن الفعلي.

هذا أمر قوي لأنه يمكنك كتابة كود يعمل مع النوع الأب، ومع ذلك فإنه يتعامل تلقائياً مع جميع الأنواع الأبناء بشكل صحيح:

class Animal {
  void speak() => print('Some sound');
}

class Dog extends Animal {
  @override
  void speak() => print('Woof!');
}

class Cat extends Animal {
  @override
  void speak() => print('Meow!');
}

void main() {
  Animal myPet = Dog();  // نوع الأب، كائن الابن
  myPet.speak();  // المخرجات: Woof!
  
  myPet = Cat();  // نفس المتغير، كائن مختلف
  myPet.speak();  // المخرجات: Meow!
}

المتغير myPet تم تعريفه كـ Animal، ولكنه يحمل Dog أو Cat. عندما يتم استدعاء speak()، تنظر Dart إلى نوع الكائن الفعلي في وقت التشغيل وتستدعي الطريقة المناسبة التي تم تجاوزها.

يمكّنك هذا من كتابة دوال مرنة تعمل مع أي فئة فرعية:

void makeAllSpeak(List<Animal> animals) {
  for (var animal in animals) {
    animal.speak();  // كل حيوان يتحدث بطريقته الخاصة
  }
}

void main() {
  var pets = [Dog(), Cat(), Dog()];
  makeAllSpeak(pets);
  // المخرجات: Woof! Meow! Woof!
}

لا تحتاج الدالة إلى معرفة أي شيء عن Dog أو Cat - فهي تعمل ببساطة مع Animal. هذا يجعل كودك أكثر قابلية للتوسع لأن إضافة أنواع حيوانات جديدة لا تتطلب أي تغييرات في الدوال الحالية.

challenge icon

التحدي

سهل

لنقم ببناء نظام آلات موسيقية يوضح تعدد الأشكال (polymorphism) بشكل عملي. ستقوم بإنشاء فئة أساسية باسم Instrument وعدة أنواع من الآلات، ثم كتابة دالة يمكنها جعل أي مجموعة من الآلات تعزف معاً - دون معرفة أنواعها المحددة.

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

  • instruments.dart: حدد التسلسل الهرمي للآلات هنا:
    • فئة Instrument مع خاصية String name ومنشئ (constructor). قم بتضمين تابع play() يطبع [name] makes a sound
    • فئة Guitar ترث من Instrument وتعمل على تجاوز (override) التابع play() ليطبع [name] strums melodically
    • فئة Drum ترث من Instrument وتعمل على تجاوز play() ليطبع [name] beats rhythmically
    • فئة Piano ترث من Instrument وتعمل على تجاوز play() ليطبع [name] plays harmoniously
    قم أيضاً بإنشاء دالة performConcert(List<Instrument> instruments) تطبع Concert begins!، ثم تمر عبر القائمة وتستدعي play() لكل آلة، وفي النهاية تطبع Concert ends!
  • main.dart: استورد ملف الآلات الخاص بك واستعرض تعدد الأشكال من خلال إنشاء فرقة موسيقية مختلطة:
    • أنشئ قائمة من نوع List<Instrument> تحتوي على Guitar باسم 'Acoustic'، و Drum باسم 'Snare'، و Piano باسم 'Grand'
    • قم بتمرير هذه القائمة إلى performConcert()

لاحظ كيف تعمل performConcert() مع النوع الأب Instrument، ومع ذلك تعزف كل آلة بطريقتها الفريدة. هذا هو تعدد الأشكال (polymorphism) - حيث يؤدي استدعاء نفس التابع إلى سلوك مختلف بناءً على النوع الفعلي للكائن.

المخرجات المتوقعة:

Concert begins!
Acoustic strums melodically
Snare beats rhythmically
Grand plays harmoniously
Concert ends!

ورقة مرجعية

تعدد الأشكال (Polymorphism) يعني "أشكالاً متعددة" - فهو يسمح لك بالتعامل مع كائنات من فئات مختلفة من خلال واجهة مشتركة. يمكن لمرجع الفئة الأب أن يشير إلى أي كائن من الفئة الابن، ويتم استدعاء الطريقة الصحيحة بناءً على نوع الكائن الفعلي في وقت التشغيل.

مثال أساسي على تعدد الأشكال:

class Animal {
  void speak() => print('Some sound');
}

class Dog extends Animal {
  @override
  void speak() => print('Woof!');
}

class Cat extends Animal {
  @override
  void speak() => print('Meow!');
}

void main() {
  Animal myPet = Dog();  // نوع الأب، كائن الابن
  myPet.speak();  // المخرجات: Woof!
  
  myPet = Cat();  // نفس المتغير، كائن مختلف
  myPet.speak();  // المخرجات: Meow!
}

يتيح تعدد الأشكال وظائف مرنة تعمل مع أي فئة فرعية:

void makeAllSpeak(List<Animal> animals) {
  for (var animal in animals) {
    animal.speak();  // كل حيوان يتحدث بطريقته الخاصة
  }
}

void main() {
  var pets = [Dog(), Cat(), Dog()];
  makeAllSpeak(pets);
  // المخرجات: Woof! Meow! Woof!
}

تعمل الوظيفة مع النوع الأب Animal دون الحاجة إلى معرفة فئات الأبناء المحددة مثل Dog أو Cat. وهذا يجعل الكود أكثر قابلية للتوسع - فإضافة أنواع جديدة لا تتطلب أي تغييرات على الوظائف الحالية.

جرّب بنفسك

import 'instruments.dart';

void main() {
  // TODO: قم بإنشاء List<Instrument> تحتوي على:
  // - Guitar باسم 'Acoustic'
  // - Drum باسم 'Snare'
  // - Piano باسم 'Grand'
  
  
  // TODO: قم باستدعاء performConcert() مع قائمة الآلات الخاصة بك
  
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming