تخطَّ إلى المحتوى

📱 شرح Flutter

المُنشئ الأساسي في Dart 3.13

الدرس 30 من 31· ⏱ 3 دقائق قراءة

💡 هذا الدرس يبني على قسم الأصناف (Classes) من درس أساسيات Dart — نفس فكرة الصنف والمُنشئ، بس بصيغة أقصر صارت مستقرة رسميًا بدءًا من Dart 3.13 (يأتي مع Flutter 3.47 المستقرة).

المشكلة: تكرار اسم الحقل ثلاث مرّات

بالصيغة التقليدية، أي حقل بالصنف بتكتب اسمه ونوعه ثلاث مرّات: مرّة كتصريح حقل، ومرّة بقائمة معاملات المُنشئ (this.x)، وأحيانًا مرّة ثالثة لو احتجت توثيقه. لصنف بسيط زي Point:

class Point {
  final int x;
  final int y;

  Point(this.x, this.y);
}

الحل: المُنشئ الأساسي (Primary Constructor)

بدءًا من Dart 3.13، تقدر تكتب قائمة المعاملات مباشرة بجانب اسم الصنف — والمعاملات اللي عليها var أو final بتصبح تلقائيًا حقولًا بالصنف وجزء من المُنشئ بنفس الوقت. نفس صنف Point أعلاه يصير سطرًا واحدًا:

class Point(final int x, final int y);

لاحظ الفاصلة المنقوطة ; بدل {} — أي صنف بلا جسم إضافي (بدون توابع أخرى) ينتهي بـ ; مباشرة.

💡 هذا مجرّد اختصار كتابة — لا يضيف أي سلوك جديد. الصنفان أعلاه متطابقان تمامًا وقت التشغيل؛ الفرق فقط عدد الأسطر.

var مقابل final بالمُنشئ الأساسي

نفس قاعدة تصريح الحقول العادية: final يعني القيمة لا تتغيّر بعد الإنشاء، var يسمح بتعديلها لاحقًا.

class Counter(var int value);   // value قابل للتعديل بعد الإنشاء

void main() {
  var c = Counter(0);
  c.value = 5;   // مسموح لأنه var
}

معاملات اختيارية ومسمّاة

المُنشئ الأساسي يدعم نفس صيغ المعاملات الاختيارية ([]) والمسمّاة ({}) اللي تعرفها من الدوال العادية:

// اختياري بقيمة افتراضية
class Point(final int x, [final int y = 0]);

// مسمّى وإجباري
class User(final String name, {required final int age});

مُنشئ مسمّى وثابت (const)

لو احتجت مُنشئًا مسمّى أو ثابتًا (const)، يُكتَب مباشرة بعد اسم الصنف بنفس ترتيب الصيغة القديمة:

// الصيغة التقليدية
class Point {
  final int x;
  final int y;
  const Point._(this.x, this.y);
}

// المُنشئ الأساسي
class const Point._(final int x, final int y);

جسم إضافي أو initializer list

لو احتجت تابعًا إضافيًا أو تحققًا بـ assert قبل الإنشاء، تقدر تضيف جسم صنف عادي بجانب المُنشئ الأساسي — القائمة بالهيدر تبقى كما هي:

class Point(final int x, final int y) {
  Point.origin() : this(0, 0);   // مُنشئ ثانوي يستدعي الأساسي

  double get distance => (x * x + y * y).toDouble();
}

💡 أي مُنشئ إضافي غير المُنشئ الأساسي لازم يكون redirecting — يستدعي المُنشئ الأساسي مباشرة أو بشكل غير مباشر، زي Point.origin() أعلاه. هذا يضمن إنه المُنشئ الأساسي ينفّذ دائمًا مع كل كائن جديد.

أخطاء شائعة

  • استخدام final على معامل عادي (غير مُعلن كحقل) بنيّة منع تعديله محليًا داخل الدالة — هذا صار خطأ ترجمة (compile-time error) بـ Dart 3.13، لأنه final بمعامل صار محجوزًا حصرًا للمعاملات المُعلِنة بالمُنشئ الأساسي. البديل لمنع إعادة تعيين معامل عادي هو قاعدة linter الجاهزة parameter_assignments.
  • نسيان رفع الحد الأدنى لإصدار SDK بملف pubspec.yaml إلى sdk: '^3.13.0' — الصيغة الجديدة غير متاحة بإصدارات Dart أقدم.
  • الظن إنه المُنشئ الأساسي يغيّر سلوك الصنف — هو اختصار كتابة فقط، الصنف يعمل بنفس الطريقة تمامًا وقت التشغيل.

🎯 التالي: الخلاصة الشاملة لمسار Flutter وخطواتك بعده.

شرح المُنشئ الأساسي في Dart 3.13 — Flutter بالعربي
المُنشئ الأساسي في Dart 3.13Flutter بالعربي · The Code Fix

📚 لمزيد من التعمّق في Flutter، راجِع التوثيق الرسمي لـ Flutter.

هل كان هذا الدرس مفيدًا؟