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

الفئات العامة

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

لقد رأيت كيف تستخدم مجموعات Dart المدمجة مثل List<String> معلمات النوع. الآن حان الوقت لإنشاء فئاتك العامة (generic classes) الخاصة التي تعمل مع أي نوع تحدده.

تستخدم الفئة العامة (generic class) معامل نوع (عادةً ما يكون T) كعنصر نائب للنوع الفعلي الذي سيتم توفيره عند إنشاء مثيل:

class Box<T> {
  T content;
  
  Box(this.content);
  
  T getContent() => content;
}

void main() {
  var stringBox = Box<String>('Hello');
  var intBox = Box<int>(42);
  
  print(stringBox.getContent());  // Hello
  print(intBox.getContent());     // 42
}

يعمل T كمتغير نوع - فعندما تقوم بإنشاء Box<String>، فإن كل T في الفئة يصبح String. يوفر لك هذا أمان النوع (type safety) دون الحاجة لكتابة فئات منفصلة لكل نوع.

يمكنك استخدام معلمات أنواع متعددة عندما يحتاج صنفك (class) إلى العمل مع أكثر من نوع واحد:

class Pair<K, V> {
  K first;
  V second;
  
  Pair(this.first, this.second);
}

void main() {
  var pair = Pair<String, int>('age', 25);
  print('${pair.first}: ${pair.second}');  // age: 25
}

تُعد الفئات العامة (Generic classes) هي الأساس لكتابة كود برمجي قابل لإعادة الاستخدام وآمن من حيث النوع (type-safe). فبدلاً من تكرار المنطق لأنواع مختلفة أو فقدان معلومات النوع باستخدام dynamic، تتيح لك القوالب العامة (generics) كتابة كود مرن لا يزال بإمكان المترجم (compiler) التحقق منه.

challenge icon

التحدي

سهل

لنقم ببناء نظام لتغليف الهدايا يستخدم أصنافاً عامة (generic classes) لإنشاء حاويات مرنة لأنواع مختلفة من العناصر. ستقوم بإنشاء صنف عام Wrapper يمكنه تغليف أي نوع من المحتوى، وصنف GiftBox بمعاملين للنوع لربط هدية مع رسالة بطاقة.

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

  • wrapper.dart: قم بتعريف الأصناف العامة هنا:
    • صنف عام Wrapper<T> مع خاصية T content ومنشئ (constructor). قم بتضمين دالة unwrap() التي تعيد المحتوى، ودالة describe() التي تطبع Wrapped: [content]
    • صنف عام GiftBox<G, C> مع خاصيتين: G gift و C card. قم بتضمين منشئ ودالة open() تطبع Gift: [gift] في سطر و Card: [card] في السطر التالي
  • main.dart: قم باستيراد ملف wrapper واستعرض الأصناف العامة مع أنواع مختلفة:
    • أنشئ Wrapper<String> يحتوي على 'Chocolate' واستدعِ describe()
    • أنشئ Wrapper<int> يحتوي على 42 واستدعِ describe()
    • أنشئ Wrapper<double> يحتوي على 3.14 واستدعِ describe()
    • اطبع سطراً فارغاً
    • أنشئ GiftBox<String, String> مع هدية 'Teddy Bear' وبطاقة 'Happy Birthday!'، ثم استدعِ open()
    • اطبع سطراً فارغاً
    • أنشئ GiftBox<int, String> مع هدية 100 (تمثل مبلغ بطاقة هدايا) وبطاقة 'Congratulations!'، ثم استدعِ open()

لاحظ كيف يعمل نفس الصنف Wrapper بسلاسة مع النصوص، والأعداد الصحيحة، والأعداد العشرية. يوضح صنف GiftBox استخدام معملين للنوع لربط أنواع مختلفة معاً - حيث يمكن أن تكون الهدية من أي نوع بينما تظل رسالة البطاقة نصاً.

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

Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14

Gift: Teddy Bear
Card: Happy Birthday!

Gift: 100
Card: Congratulations!

ورقة مرجعية

تستخدم الأصناف العامة (Generic classes) معاملات النوع (مثل T) كعناصر نائبة للأنواع الفعلية المحددة عند إنشاء المثيلات:

class Box<T> {
  T content;
  
  Box(this.content);
  
  T getContent() => content;
}

void main() {
  var stringBox = Box<String>('Hello');
  var intBox = Box<int>(42);
  
  print(stringBox.getContent());  // Hello
  print(intBox.getContent());     // 42
}

عند إنشاء Box<String>، يصبح كل T في الصنف String، مما يوفر سلامة النوع (type safety) دون الحاجة إلى أصناف منفصلة لكل نوع.

استخدم معاملات نوع متعددة عند العمل مع أكثر من نوع واحد:

class Pair<K, V> {
  K first;
  V second;
  
  Pair(this.first, this.second);
}

void main() {
  var pair = Pair<String, int>('age', 25);
  print('${pair.first}: ${pair.second}');  // age: 25
}

جرّب بنفسك

import 'wrapper.dart';

void main() {
  // TODO: قم بإنشاء Wrapper<String> يحتوي على 'Chocolate' واستدعِ describe()
  
  // TODO: قم بإنشاء Wrapper<int> يحتوي على 42 واستدعِ describe()
  
  // TODO: قم بإنشاء Wrapper<double> يحتوي على 3.14 واستدعِ describe()
  
  // TODO: اطبع سطراً فارغاً
  
  // TODO: قم بإنشاء GiftBox<String, String> مع الهدية 'Teddy Bear' 
  // والبطاقة 'Happy Birthday!'، ثم استدعِ open()
  
  // TODO: اطبع سطراً فارغاً
  
  // TODO: قم بإنشاء GiftBox<int, String> مع الهدية 100 
  // والبطاقة 'Congratulations!'، ثم استدعِ open()
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming