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

حقول Final و Const

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

عند التصريح عن الحقول في فئة (class)، يمكنك استخدام final أو const للتحكم في ما إذا كان يمكن تغيير القيم بعد التهيئة. كلاهما ينشئ قيمًا غير قابلة للتغيير، لكنهما يعملان بشكل مختلف.

يمكن تعيين قيمة الحقل final مرة واحدة فقط، ولكن يتم تحديد قيمته في وقت التشغيل (runtime). يمكنك تعيينه عند التصريح أو من خلال المنشئ (constructor):

class Person {
  final String name;
  final DateTime createdAt = DateTime.now();
  
  Person(this.name);
}

Person p = Person('Alice');
// p.name = 'Bob';  // خطأ: لا يمكن إعادة تعيين حقل final

يتم تعيين name عند إنشاء الكائن، ويقوم createdAt بالتقاط الوقت الحالي. يتم قفل كلتا القيمتين بعد التهيئة.

يجب أن يمتلك الحقل من النوع static const قيمة معروفة في وقت التصريف. وهو ينتمي إلى الفئة نفسها ويتم مشاركته عبر جميع المثيلات:

class Circle {
  static const double pi = 3.14159;
  final double radius;
  
  Circle(this.radius);
  
  double get area => Circle.pi * radius * radius;
}

الفرق الرئيسي: يمكن لحقول final أن تحمل قيمًا يتم حسابها في وقت التشغيل (مثل DateTime.now())، بينما تتطلب const ثوابت وقت التجميع. لا يمكن أن تكون حقول المثيل const بشكل مباشر - يُسمح فقط بـ static const على مستوى الفئة (class).

challenge icon

التحدي

سهل

لنقم ببناء نظام كتالوج منتجات يوضح الفرق بين حقول final و static const. ستقوم بإنشاء منتجات بخصائص غير قابلة للتغيير وقيم تكوين مشتركة.

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

  • product.dart: قم بتعريف فئة Product التي تمثل عنصراً في متجر. يجب أن تحتوي الفئة الخاصة بك على:
    • static const double taxRate مضبوطة على 0.08 (معدل ضريبة 8% مشترك بين جميع المنتجات)
    • static const String currency مضبوطة على 'USD'
    • final String name لاسم المنتج (يتم تعيينه عبر المنشئ)
    • final double basePrice للسعر الأساسي للمنتج (يتم تعيينه عبر المنشئ)
    • final String sku (وحدة حفظ المخزون) التي تجمع بين بادئة واسم المنتج، ويتم حسابها في قائمة التهيئة كـ 'SKU-' متبوعة بالاسم بأحرف كبيرة (uppercase)
    • منشئ (constructor) يأخذ name و basePrice
    • مسترجع (getter) باسم priceWithTax يحسب السعر شاملاً الضريبة
    • دالة display() تقوم بطباعة معلومات المنتج
  • main.dart: قم باستيراد فئة المنتج الخاصة بك وإنشاء منتجين:
    • 'Laptop' بسعر أساسي 999.99
    • 'Mouse' بسعر أساسي 29.99
    قم باستدعاء display() لكل منتج بالترتيب المذكور أعلاه.

يجب أن تطبع دالة display() بهذا التنسيق الدقيق:

[sku] - [name]: [basePrice] [currency] (with tax: [priceWithTax] [currency])

قم بتقريب priceWithTax إلى منزلتين عشريتين باستخدام toStringAsFixed(2) عند العرض.

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

SKU-LAPTOP - Laptop: 999.99 USD (with tax: 1079.99 USD)
SKU-MOUSE - Mouse: 29.99 USD (with tax: 32.39 USD)

ورقة مرجعية

استخدم final للحقول التي يتم تعيينها مرة واحدة في وقت التشغيل (runtime) ولا يمكن تغييرها بعد ذلك. استخدم static const للثوابت التي يتم تحديدها في وقت التجميع (compile-time) وتتم مشاركتها عبر جميع مثيلات الفئة (class).

يتم تعيين حقول final في وقت التشغيل ويمكن تهيئتها في الإعلان أو في منشئ الفئة (constructor):

class Person {
  final String name;
  final DateTime createdAt = DateTime.now();
  
  Person(this.name);
}

يجب أن تحتوي حقول static const على قيم ثابتة في وقت التجميع وتكون تابعة للفئة نفسها:

class Circle {
  static const double pi = 3.14159;
  final double radius;
  
  Circle(this.radius);
  
  double get area => Circle.pi * radius * radius;
}

يمكنك حساب قيم حقول final في قائمة التهيئة (initializer list):

class Product {
  final String name;
  final String sku;
  
  Product(this.name) : sku = 'SKU-${name.toUpperCase()}';
}

الاختلافات الرئيسية:

  • final: قيم وقت التشغيل، ويمكن أن تكون مختلفة لكل مثيل (instance)
  • static const: ثوابت وقت التجميع، وتتم مشاركتها عبر جميع المثيلات
  • لا يمكن أن تكون حقول المثيلات const بشكل مباشر - يُسمح فقط بـ static const

جرّب بنفسك

import 'product.dart';

void main() {
  // TODO: قم بإنشاء منتج يسمى 'Laptop' بسعر أساسي 999.99
  
  // TODO: قم بإنشاء منتج يسمى 'Mouse' بسعر أساسي 29.99
  
  // TODO: قم باستدعاء display() لكل منتج بالترتيب (Laptop أولاً، ثم Mouse)
  
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming