الأنماط والمطابقة (Patterns & Matching - 3.0)
جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 87 من 110.
قدمت Dart 3 مطابقة الأنماط (pattern matching)، وهي طريقة قوية لتفكيك البيانات وفحصها في تعبير واحد. تتيح لك الأنماط استخراج القيم من الكائنات، والتحقق من بنيتها، وربط المتغيرات - كل ذلك في آن واحد.
لقد رأيت بالفعل التفكيك الأساسي مع السجلات. تعمل الأنماط على توسيع ذلك ليشمل الكائنات والقوائم والخرائط:
void main() {
// أنماط القوائم
var numbers = [1, 2, 3];
var [a, b, c] = numbers;
print('$a, $b, $c'); // 1, 2, 3
// أنماط الخرائط
var user = {'name': 'Alice', 'age': 30};
var {'name': name, 'age': age} = user;
print('$name is $age'); // Alice is 30
}تصبح الأنماط (Patterns) قوية بشكل خاص في تعبيرات switch. يمكنك المطابقة بناءً على النوع والقيمة والبنية في آنٍ واحد:
String describe(Object obj) {
return switch (obj) {
int n when n < 0 => 'Negative number',
int n => 'Positive number: $n',
String s => 'String of length ${s.length}',
[int first, ...] => 'List starting with $first',
_ => 'Something else',
};
}
void main() {
print(describe(-5)); // رقم سالب
print(describe(42)); // رقم موجب: 42
print(describe([1, 2, 3])); // قائمة تبدأ بـ 1
}تضيف جملة when شروطاً إلى الأنماط، وتطابق ... العناصر المتبقية في القائمة. تعمل الشرطة السفلية _ كرمز بديل يطابق أي شيء. وبالاقتران مع الأصناف المختومة (sealed classes)، تتيح الأنماط معالجة شاملة وآمنة للأنواع (type-safe) لهياكل البيانات المعقدة.
التحدي
سهللنقم ببناء مصنف بيانات يستخدم مطابقة الأنماط (pattern matching) لتحليل وتصنيف أنواع مختلفة من المدخلات! ستقوم بإنشاء نظام يمكنه تحديد ووصف هياكل البيانات المختلفة باستخدام ميزات مطابقة الأنماط القوية في Dart 3.
ستقوم بتنظيم الكود الخاص بك في ملفين:
classifier.dart: أنشئ دالة تسمىclassifyتأخذ معاملًا من نوعObjectوتعيد وصفًا من نوعString. استخدم تعبير switch مع مطابقة الأنماط للتعامل مع هذه الحالات:- القائمة الفارغة
[]يجب أن تعيدEmpty list - القائمة التي تحتوي على عنصر صحيح واحد بالضبط يجب أن تعيد
Single item: [value] - القائمة التي تحتوي على عنصرين بالضبط يجب أن تعيد
Pair: [first] and [second] - القائمة التي تبدأ بعدد صحيح متبوعًا بعناصر أخرى يجب أن تعيد
List starting with [first], length: [total length](استخدم نمط البقية...) - الخريطة (map) التي تحتوي على المفتاحين
'name'و'age'يجب أن تعيد[name] is [age] years old(استخدم تفكيك نمط الخريطة) - العدد الصحيح السالب (استخدم بند
when) يجب أن يعيدNegative: [value] - العدد الصحيح الذي يساوي صفرًا يجب أن يعيد
Zero - أي عدد صحيح آخر يجب أن يعيد
Positive: [value] - أي قيمة أخرى يجب أن تعيد
Unknown type
- القائمة الفارغة
main.dart: استورد المصنف الخاص بك واستعرض مطابقة الأنماط مع مدخلات متنوعة. اطبع نتيجة تصنيف كل من هذه القيم:- قائمة فارغة
[] - قائمة تحتوي على عنصر واحد:
[42] - قائمة تحتوي على عنصرين:
['hello', 'world'] - قائمة أطول:
[1, 2, 3, 4, 5] - خريطة:
{'name': 'Alice', 'age': 25} - العدد الصحيح
-10 - العدد الصحيح
0 - العدد الصحيح
99
- قائمة فارغة
يجمع هذا التحدي بين أنماط القوائم، وأنماط الخرائط، وبند when للحماية، ونمط البقية (...) - وهي جميع ميزات مطابقة الأنماط الرئيسية من الدرس!
المخرجات المتوقعة:
Empty list
Single item: 42
Pair: hello and world
List starting with 1, length: 5
Alice is 25 years old
Negative: -10
Zero
Positive: 99ورقة مرجعية
قدمت Dart 3 مطابقة الأنماط (pattern matching) لتفكيك البيانات وفحصها في تعبير واحد.
أنماط القوائم (List Patterns)
استخراج القيم من القوائم:
var numbers = [1, 2, 3];
var [a, b, c] = numbers;
print('$a, $b, $c'); // 1, 2, 3أنماط الخرائط (Map Patterns)
تفكيك الخرائط حسب المفتاح:
var user = {'name': 'Alice', 'age': 30};
var {'name': name, 'age': age} = user;
print('$name is $age'); // Alice is 30تعبيرات Switch مع الأنماط
المطابقة بناءً على النوع، القيمة، والبنية:
String describe(Object obj) {
return switch (obj) {
int n when n < 0 => 'Negative number',
int n => 'Positive number: $n',
String s => 'String of length ${s.length}',
[int first, ...] => 'List starting with $first',
_ => 'Something else',
};
}ميزات الأنماط
- بند
when: يضيف شروطاً للأنماط ...(نمط البقية): يطابق العناصر المتبقية في القائمة_(العنصر النائب): يطابق أي شيء
جرّب بنفسك
import 'classifier.dart';
void main() {
// TODO: استخدم الدالة classify لتصنيف كل قيمة
// وطباعة النتائج
// اختبار مع قائمة فارغة
print(classify([]));
// TODO: اختبار مع قائمة تحتوي على عنصر واحد: [42]
// TODO: اختبار مع قائمة تحتوي على عنصرين: ['hello', 'world']
// TODO: اختبار مع قائمة أطول: [1, 2, 3, 4, 5]
// TODO: اختبار مع map: {'name': 'Alice', 'age': 25}
// TODO: اختبار مع العدد الصحيح -10
// TODO: اختبار مع العدد الصحيح 0
// TODO: اختبار مع العدد الصحيح 99
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع