محتويات الدورة
Dart
الأساسيات: القيم والغياب والمجموعات والكائنات الصالحة
العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة
التكامل: الأهداف والموارد والتحقق والأدلة

Dart / العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة / الدرس 9

استخدام الأنواع العامة دون افتراضات كتابة غير آمنة

احفظ أنواع العناصر واختر قيودا ذات معنى، وافهم التغاير وفحوص التشغيل عند حدود المجموعات المعدلة في Dart.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • اشرح لماذا لا يجعل المرجع الأوسع الكائن المعدل الأضيق قابلا لكل قيمة.
  • ميّز فحص الأنواع العامة المحفوظة وقت التشغيل ومناظير cast الكسولة والنسخ المتحققة.

يحفظ معامل النوع علاقة المدخل بالمخرج

تحفظ الدالة العامة نوع عناصر المستدعي بدلا من إعادة dynamic. يفيد معامل النوع عندما يعبر عن علاقة، مثل إعادة إحدى قيم T المعطاة. أضف قيدا فقط إذا احتاج التنفيذ عمليات يضمنها. يستبعد Object القيمة null بينما يشملها Object?؛ فقد يغير القيد الاختيارية والأعضاء المتاحة معا. تجنب إعلان T غير مقيد ثم تحويله قسريا لنوع مفضل داخل الجسم. صرّح بالقدرة المطلوبة أو اقبل معامل سلوك يزوّد العملية.

أعد نوع المستدعي عبر مساعد عام صغير

يعيد المساعد أول عنصر أو null للفراغ. تظهر T? الغياب حتى لو كان T غير خال. لا يثبت ذلك ثبات قائمة اعتباطية أو استحالة فشل التكرار. يستخدم المثال قوائم ثابتة المدخل من int وString لتوضيح الأنواع المستنتجة. تظل الواجهة العامة مطالبة بتفسير هل تعيد مرجع كائن قائم أو نسخة، وهل تمر على المدخل مرة واحدة. تحفظ الصياغة العامة علاقة أنواع، ولا تنشئ ضمانات ملكية أو عمر.

dart نتيجة قابلة للخلو تحفظ نوع العنصر
T? firstOrNull<T>(List<T> values) => values.isEmpty ? null : values.first;
void main() {
  final number = firstOrNull<int>(<int>[7, 8]);
  final name = firstOrNull<String>(<String>[]);
  print(number);
  print(name ?? 'absent');
}
الناتج المتوقع
7
absent

المخرج المتوقع 7 ثم absent. تعيد الدالة القيمة الأولى القائمة ولا تستنسخها. لم يُترجم المصدر أو يُفحص بأداة تحليل Dart.

تسمح Dart بالتغاير وتفحص الكتابة غير الآمنة

تكون أصناف Dart العامة متغايرة في معاملاتها افتراضيا. لذلك يمكن الإشارة إلى List<int> بوصفها List<num>، لكن ذلك لا يحول تخزينها الفعلي إلى قائمة تقبل double. تُفحص كتابة غير متوافقة لاحقا عبر المرجع الأوسع وقت التشغيل وقد تفشل. يختلف هذا عن لغات ترفض الإسناد الأوسع نفسه. فضّل مجموعة أوسع منفصلة إذا احتاج المستدعي إضافة قيم أوسع. لا تستخدم cast لإقناع المحلل بأمان التعديل؛ افحص عقد الكائن التشغيلي ومراجعه الأخرى.

ابن حاوية أوسع عندما تلزم كتابة قيم أوسع

ينشئ المثال List<num> صراحة من أعداد صحيحة ثم يضيف double إلى القائمة الجديدة. تحتفظ الأصلية بوعد عناصر int. هذا نسخ سطحي للحاوية؛ وستشترك الطريقة نفسها في كائنات عناصر معدلة إذا كانت العناصر مرجعية. تُشرح العملية غير الآمنة في النثر دون تنفيذها أو اختلاق أثر استثناء لها. تعد فحوص التشغيل جزءا مهما من سلامة أنواع Dart، لكن تجنب كتابة فاشلة يمكن منعها أوضح من catch حول كل تعديل مجموعة.

dart منظور أوسع ونسخة أوسع مقصودة
void main() {
  final integers = <int>[1, 2];
  final List<num> view = integers;
  final wider = <num>[...integers];
  wider.add(2.5);
  print(view.length);
  print(wider.join('|'));
  print(integers.join('|'));
}
الناتج المتوقع
2
1|2|2.5
1|2

المخرج المتوقع 2 ثم 1|2|2.5 ثم 1|2. أما إضافة 2.5 إلى view فتخالف عقد كتابة List<int> الأصلية وقد تفشل وقت التشغيل؛ ولا ينفذها المثال. لم تُنفّذ Dart.

منظور cast ليس تحققا متحمسا لكل البيانات

تحتفظ Dart بمعلومات أنواع عامة وقت التشغيل لفحوص مناسبة، خلاف افتراض اختفاء كل المعاملات. ومع ذلك لا تصبح List<dynamic> مفكوكة من الخارج List<String> متحققة تلقائيا. قد تعرض cast منظورا يفحص العنصر عند الوصول، فيفشل المحتوى الخاطئ لاحقا. اختر تحويلا متحمسا متحققا إذا احتاج الحد نقطة رفض واحدة واضحة. افحص كل عنصر مطلوب وقاعدة مجال، واحفظ سببا آمنا، ولا تحذف الخطأ بصمت إلا بسياسة ترشيح معلنة. تدعم الأنواع المحفوظة الفحص ولا تستبدل التحقق الدلالي.

الأخطاء الشائعة وإصلاحها

تفشل كتابة double عبر مرجع List<num>.

لماذا يحدث؟
يبقى الكائن الأصلي List<int> بعقد كتابة أضيق.
كيف تصلحه؟
أنشئ حاوية أوسع فعلا أو التزم بنوع العناصر الأصلي.
كيف تتجنب تكراره؟
راجع التغاير مع جميع مسارات التعديل.

يفشل cast بعد وقت من قبول البيانات الخارجية.

لماذا يحدث؟
أجّل منظور cast الكسول فحص العناصر.
كيف تصلحه؟
تحقق وانسخ عند الحد إذا لزم رفض فوري.
كيف تتجنب تكراره؟
وثّق هل التحويل تحقق متحمس أم منظور مفحوص.

تستدعي دالة عامة عمليات غير مضمونة لـT.

لماذا يحدث؟
لم تمثل القدرة المطلوبة بقيد أو معامل.
كيف تصلحه؟
اذكر القيد الضيق أو مرّر السلوك المطلوب صراحة.
كيف تتجنب تكراره؟
صمّم العملية قبل اختيار صياغة عامة واسعة.

اختبر فهمك

1. لماذا لا ينشئ إسناد List<int> إلى List<num> كائن List<num> جديدا؟

اعرض الحل المشروح

يغير الإسناد نوع المرجع الساكن لا هوية القائمة أو تنفيذها. يمكن للقراءة عرض int كـnum بأمان، لكن يجب أن تحترم الكتابة نوع العناصر التشغيلي الأصلي. أنشئ قائمة أوسع مستقلة إذا لزم إدخال double، وتذكر أن نسخ الحاوية لا ينسخ العناصر المرجعية بعمق.

2. هل ينبغي لواجهة حذف كل عنصر غير نصي بصمت عند تحويل قائمة تسميات خارجية؟

اعرض الحل المشروح

فقط إذا كانت التصفية الجزئية سياسة المنتج المعلنة. وإلا فقد تحول مدخلا مشوها إلى نجاح يبدو كاملا. تحقق من جميع العناصر وأعد رفضا منظما أو تقريرا بالمقبول والمرفوض. تساعد معلومات نوع التشغيل على تحديد الأنواع، وتبقى الواجهة مسؤولة عن معنى النقص.

أهم ما تعلمته

  • يتيح التغاير قراءات مفيدة وقد ينقل الكتابة غير المتوافقة إلى فحوص التشغيل.
  • للنسخة المتحققة والمنظور المفحوص وعود مختلفة في التوقيت والملكية.

المراجع الرسمية