Dart / العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة / الدرس 7
استخدام السجلات والأنماط للحفاظ على بنية البيانات
أعد قيما متعددة باستخدام السجلات، وطابق البنى المعروفة بالتفكيك وأنماط الأنواع والحراس وتعبيرات switch.
في هذه الصفحة
أهداف الدرس
- اشرح البنية التركيبية للسجل، وميّز ثبات حقوله من قابلية تعديل الكائنات التي تشير إليها.
- اختر نمطا يفحص الشرط المقصود، دون اعتبار تفكيك البيانات تحققا كاملا منها.
يجمع السجل قيما دون تعريف صنف جديد
السجلات قيم مركبة ثابتة الحجم ذات حقول موضعية أو مسماة أو الاثنين معا. أنواعها تركيبية؛ إذ يحدد الشكل عدد الحقول الموضعية وأنواعها، وأسماء الحقول المسماة وأنواعها. لا ينشئ اختلاف ترتيب الحقول المسماة نوع سجل مختلفا، لكن تغيير اسم أحدها يغير الشكل. يمكن أن تمنح typedef اسما مستعارا مفيدا دون إنشاء هوية اسمية جديدة. استخدم السجل لنتيجة صغيرة مترابطة، واختر صنفا عندما يحتاج المجال بناء مضبوطا أو سلوكا أو تجريدا مسمى مستقرا، بدلا من حزمة قيم مجهولة.
أعد ملخصا مترابطا بدلا من متغيرات منفصلة
تعد الدالة أدناه القيم الموجبة مقبولة وكل عدد صحيح آخر معطى مرفوضا. تعيد سجلا مسمى ليظهر معنى كل عد عند حد الدالة. يربط التفكيك الحقول بمتغيرات محلية دون سلسلة افتراضات عن فهارسها. يحتاج المثال دعم السجلات والأنماط الذي بدأ مع Dart 3، وعلى المشروع إعلان نسخة لغة يدعمها قيد SDK. لم يتوفر محلل Dart أو بيئة تشغيلها أثناء التأليف، لذلك فالمخرج المعروض توقع مبني على التحليل لا نتيجة اختبار مرصودة.
({int accepted, int rejected}) summarize(List<int> values) {
final accepted = values.where((value) => value > 0).length;
return (accepted: accepted, rejected: values.length - accepted);
}
void main() {
final summary = summarize(<int>[2, 0, -1, 3]);
final (accepted: good, rejected: bad) = summary;
print('accepted=$good');
print('rejected=$bad');
}
accepted=2
rejected=2
المخرج المتوقع accepted=2 ثم rejected=2. تحفظ تسميات السجل المعنيين، ويختار المستهلك الاسمين المحليين good وbad. لم يُترجم هذا المصدر.
تستطيع الأنماط الفحص والربط معا
يمكن للنمط فحص نوع القيمة أو شكلها وربط أجزائها لاستخدامها في فرع ناجح. تفيد if-case عندما ينبغي أن يسلك عدم التطابق مسارا آخر، بينما يفترض نمط التصريح تطابق البنية عند حد ذلك التصريح. تعبر أنماط القوائم والخرائط عن شروط تركيبية محددة، لا عن كل قاعدة عمل داخل القيم. لا يثبت نمط يربط int أن العدد موجب أو ضمن حد التطبيق أو مسموح للمستدعي. أبق هذه الفحوص الدلالية صريحة بحارس أو مرحلة تحقق لاحقة.
يضيف الحارس شرطا إلى تطابق ناجح
ينتج تعبير switch قيمة ويجب أن يغطي مجال المدخلات الممكنة. يُفحص حارس when بعد تطابق النمط، فيتاح المتغير المربوط داخل شرطه. يهم ترتيب الفروع عندما تتداخل الأنماط. يقبل المثال int موجبا أولا، ويعالج بقية الأعداد الصحيحة منفصلة، ثم يغطي الباقي بعلامة شاملة. يشمل الفرع الأخير null والنصوص، فلا يدعي أن كل قيمة غير موجبة من النوع نفسه. تجنب نمطا شاملا مبكرا يحجب السياسة المحددة أو يخفي بديلا جديدا.
String classify(Object? value) => switch (value) {
int count when count > 0 => 'positive:$count',
int _ => 'nonpositive',
_ => 'not-an-int',
};
void main() {
print(classify(3));
print(classify(0));
print(classify('3'));
}
positive:3
nonpositive
not-an-int
المخرج المتوقع positive:3 ثم nonpositive ثم not-an-int. لا يُحلَّل النص إلى عدد ضمنيا. تلزم صياغة الأنماط وتعبيرات switch في Dart 3؛ ولا يُدعى تنفيذ البرنامج.
لا تجمّد مساواة السجل نموذجا بعمق
لا يعاد إسناد حقول السجل، وتعتمد مساواته على تطابق الشكل وعقد مساواة كل حقل مقابل. قد يشير حقل إلى قائمة قابلة للتعديل يتغير محتواها، ولا تصبح مساواة تلك القائمة تلقائيا مقارنة عميقة لعناصرها. تغير إضافة حقل عقد السجل وقد تكسر مستدعيا يفكك شكله القديم. في الواجهات العامة، فكّر هل يقدم الصنف حدا أوضح للتطور. تحسن الأنماط الوضوح المحلي، لكن البايتات الخارجية ما زالت تحتاج فكا وحدود حجم وتحقق أنواع وسياسة صريحة للحقول والقيم المجهولة.
الأخطاء الشائعة وإصلاحها
يُعاد اسم حقل سجل كأنه تسمية محلية فقط.
- لماذا يحدث؟
- تدخل أسماء الحقول المسماة في الشكل التركيبي للسجل.
- كيف تصلحه؟
- عامل إعادة الاسم كتغيير في العقد أمام المستدعي.
- كيف تتجنب تكراره؟
- افحص التفكيك وأنواع الرد قبل تطوير سجل عام.
يُقبل عدد صحيح مطابق رغم خرقه قاعدة نطاق.
- لماذا يحدث؟
- اختلط تطابق النوع بالتحقق من المجال.
- كيف تصلحه؟
- أضف حارسا صريحا أو تحويلا متحققا للنطاق.
- كيف تتجنب تكراره؟
- اختبر عدم تطابق النوع والرفض الدلالي كحالتين منفصلتين.
يوصف سجل يحوي قائمة بأنه ثابت بعمق.
- لماذا يحدث؟
- اختلط ثبات الحقول بثبات الكائنات المشار إليها.
- كيف تصلحه؟
- استخدم نماذج عناصر ثابتة أو سياسة لقطات صريحة.
- كيف تتجنب تكراره؟
- افحص المراجع الداخلية قبل الوعد بثبات محتوى السجل.
اختبر فهمك
1. هل يثبت نمط خريطة يحتوي id وcount أن حمولة دفعة خارجية صالحة بالكامل؟
اعرض الحل المشروح
لا. يفحص الشروط التركيبية والنوعية التي يذكرها النمط فقط. قد يكون المعرف فارغا أو غير مأذون، وقد يخالف العدد النطاق، وقد تحتاج الحقول الإضافية والحجم إلى سياسة. فك البيانات وتحقق من كل معنى مطلوب ثم أنشئ تمثيلا محليا موثوقا. لا توسع ادعاء النمط إلى شروط لا يعبّر عنها.
2. متى يفضّل صنف مسمى على سجل كبير ذي حقول كثيرة ضعيفة الترابط؟
اعرض الحل المشروح
عندما تهم ضوابط الإنشاء أو السلوك أو تطور المعنى أو تجريد عام مستقر. يسمّي الصنف المسؤولية وقد يقيد التراكيب غير الصالحة بواجهته. يبقى السجل مفيدا لنتيجة تركيبية صغيرة، لكن زيادة حقوله ليست بديلا جيدا تلقائيا عن نمذجة مفهوم متماسك. راجع تغييرات المستدعين واحتياجات التحقق قبل الاختيار.
أهم ما تعلمته
- تكشف الأنماط شروط الشكل والنوع المعلنة، وتعبّر الحراس عن السياسة الإضافية.
- السجلات قيم تركيبية تحتفظ كائناتها الداخلية بعقودها الخاصة.