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

قيود الأنماط العامة

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

أحياناً تحتاج إلى أن يمتلك النوع العام (generic type) قدرات معينة. على سبيل المثال، إذا كنت تريد مقارنة العناصر أو الوصول إلى خصائص محددة، فإن T غير المقيد لن يضمن وجود هذه الميزات. تسمح لك القيود العامة (Generic constraints) بتقييد معاملات النوع لأنواع محددة أو فئاتها الفرعية.

استخدم الكلمة المفتاحية extends لتقييد معلمة النوع:

class NumberBox<T extends num> {
  T value;
  
  NumberBox(this.value);
  
  T doubled() => (value * 2) as T;
}

void main() {
  var intBox = NumberBox<int>(5);
  var doubleBox = NumberBox<double>(3.5);
  
  print(intBox.doubled());    // 10
  print(doubleBox.doubled()); // 7.0
  
  // var stringBox = NumberBox<String>('hi');  // خطأ!
}

لأن T extends num، يعرف المترجم أن value يدعم العمليات الحسابية مثل الضرب. بدون هذا القيد، فإن استدعاء value * 2 سيفشل.

تعمل القيود مع التسلسلات الهرمية للفئات الخاصة بك أيضاً:

abstract class Animal {
  String get name;
}

class Dog extends Animal {
  String get name => 'Dog';
}

class Shelter<T extends Animal> {
  List<T> animals = [];
  
  void add(T animal) => animals.add(animal);
  
  void printNames() {
    for (var animal in animals) {
      print(animal.name);  // آمن: T تضمن وجود 'name'
    }
  }
}

تجمع قيود الأنواع العامة (Generic constraints) بين مرونة الأنواع العامة وأمان معرفة العمليات المتاحة لنوع البيانات الخاص بك.

challenge icon

التحدي

سهل

لنقم ببناء آلة حاسبة للإحصائيات تعمل فقط مع الأنواع الرقمية! ستقوم بإنشاء فئة عامة (generic class) مع قيد يضمن إمكانية استخدامها فقط مع الأرقام، مما يسمح لك بإجراء العمليات الحسابية بأمان على القيم المخزنة.

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

  • stats.dart: أنشئ فئة عامة Stats<T extends num> تدير قائمة من القيم الرقمية:
    • List<T> تسمى values لتخزين الأرقام
    • منشئ (constructor) يقوم بتهيئة القائمة بالقيم المقدمة
    • دالة sum() تعيد مجموع كل القيم كـ num
    • دالة min() تعيد أصغر قيمة كـ T
    • دالة max() تعيد أكبر قيمة كـ T
    • دالة printStats() تعرض الإحصائيات بطريقة منسقة
  • main.dart: استورد ملف الإحصائيات الخاص بك واستعرض الفئة العامة المقيدة بأنواع رقمية مختلفة:
    • أنشئ Stats<int> بالقيم [10, 25, 5, 30, 15] واستدعِ printStats()
    • اطبع سطراً فارغاً
    • أنشئ Stats<double> بالقيم [3.5, 1.2, 4.8, 2.1] واستدعِ printStats()

يجب أن تقوم دالة printStats() بإخراج ثلاثة أسطر تعرض المجموع، والحد الأدنى، والحد الأقصى للقيم. نظرًا لأن T extends num، يمكنك استخدام معاملات المقارنة والعمليات الحسابية بأمان على القيم - وهو أمر لن يكون ممكنًا مع نوع عام غير مقيد.

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

Sum: 85
Min: 5
Max: 30

Sum: 11.6
Min: 1.2
Max: 4.8

ورقة مرجعية

تقيد القيود العامة (Generic constraints) معلمات النوع لأنواع محددة أو فئاتها الفرعية باستخدام الكلمة الأساسية extends:

class NumberBox<T extends num> {
  T value;
  
  NumberBox(this.value);
  
  T doubled() => (value * 2) as T;
}

مع T extends num، يعرف المترجم أن value تدعم العمليات الرقمية مثل الضرب.

تعمل القيود أيضاً مع التسلسلات الهرمية للفئات المخصصة:

abstract class Animal {
  String get name;
}

class Shelter<T extends Animal> {
  List<T> animals = [];
  
  void printNames() {
    for (var animal in animals) {
      print(animal.name);  // آمن: T تضمن وجود 'name'
    }
  }
}

توفر القيود العامة المرونة مع ضمان سلامة النوع (type safety) والعمليات المتاحة.

جرّب بنفسك

import 'stats.dart';

void main() {
  // TODO: [10, 25, 5, 30, 15] بقيم Stats<int> قم بإنشاء
  // printStats() واستدعِ
  
  // TODO: قم بطباعة سطر فارغ
  
  // TODO: [3.5, 1.2, 4.8, 2.1] بقيم Stats<double> قم بإنشاء
  // printStats() واستدعِ
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming