تعمق في Getters و Setters
جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 33 من 110.
تصبح أدوات الجلب (Getters) والتعيين (setters) أدوات قوية للتغليف (encapsulation) عند دمجها مع الحقول الخاصة (private fields). فهي تتيح لك عرض واجهة عامة نظيفة مع الاحتفاظ بالتحكم الكامل في كيفية الوصول إلى البيانات وتعديلها.
من الأنماط الشائعة إقران حقل خاص (private field) مع دالة جلب (getter) ودالة تعيين (setter) عامتين تتضمنان التحقق من الصحة:
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15; // الحد الأدنى للصفر المطلق
} else {
_celsius = value;
}
}
}يمكن لدوال التعيين (Setters) فرض قواعد العمل، مما يضمن عدم دخول الكائن الخاص بك في حالة غير صالحة أبداً.
يمكنك أيضاً إنشاء getters محسوبة تستمد قيمها من بيانات خاصة:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height; // محسوبة
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}أحياناً قد ترغب في الوصول للقراءة فقط. ببساطة، قم بتوفير دالة جلب (getter) بدون دالة تعيين (setter):
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt; // للقراءة فقط
}يوفر هذا النمط للكود الخارجي إمكانية رؤية البيانات مع منع أي تعديلات - فالحقل الخاص (private field) المقترن بـ getter فقط ينشئ وصولاً حقيقياً للقراءة فقط.
التحدي
سهللنقم ببناء نظام مخزون منتجات يستعرض قوة أدوات الحصول (getters) وأدوات التعيين (setters) للتحكم في الوصول إلى البيانات. ستقوم بإنشاء فئة (class) تحمي بياناتها الداخلية مع توفير خصائص محسوبة وتحقق من الصحة.
ستقوم بتنظيم الكود الخاص بك في ملفين:
product.dart: قم بتعريف فئةProductتدير المخزون مع تغليف (encapsulation) مناسب. يجب أن يحتوي منتجك على:- متغير عام
String name - متغير خاص
double _price - متغير خاص
int _quantity - منشئ (constructor) يأخذ القيم الثلاث جميعها
- أداة الحصول
priceالتي تعيد السعر الخاص - أداة التعيين
priceالتي تقبل فقط القيم الأكبر من0(تجاهل القيم غير الصالحة) - أداة الحصول
quantityالتي تعيد الكمية الخاصة - أداة التعيين
quantityالتي تقبل فقط قيم0أو أكبر (تجاهل القيم السالبة) - أداة الحصول المحسوبة
totalValueالتي تعيد_price * _quantity - أداة الحصول المحسوبة
isInStockالتي تعيدtrueإذا كانت الكمية أكبر من0 - أداة الحصول للقراءة فقط
skuالتي تنشئ SKU بسيطاً عن طريق إرجاع أول 3 أحرف من الاسم بأحرف كبيرة متبوعة بالكمية (على سبيل المثال،LAP25لـ "Laptop" بكمية 25) - دالة
displayProduct()تعرض تفاصيل المنتج
- متغير عام
main.dart: قم باستيراد فئة المنتج الخاصة بك ووضح كيف تتحكم أدوات الحصول والتعيين في الوصول:- أنشئ منتجاً باسم
'Laptop'بسعر999.99وكمية25 - استدعِ
displayProduct() - اطبع
In stock: [isInStock] - اطبع
SKU: [sku] - حاول تعيين السعر إلى
-50.0(يجب تجاهله) - عين السعر إلى
899.99(تغيير صالح) - حاول تعيين الكمية إلى
-10(يجب تجاهله) - عين الكمية إلى
0(تغيير صالح) - استدعِ
displayProduct() - اطبع
In stock: [isInStock] - اطبع
SKU: [sku]
- أنشئ منتجاً باسم
يجب أن تطبع الدالة displayProduct() بهذا التنسيق:
--- Product Info ---
Name: [name]
Price: $[price]
Quantity: [quantity]
Total Value: $[totalValue]المخرجات المتوقعة:
--- Product Info ---
Name: Laptop
Price: $999.99
Quantity: 25
Total Value: $24999.75
In stock: true
SKU: LAP25
--- Product Info ---
Name: Laptop
Price: $899.99
Quantity: 0
Total Value: $0.0
In stock: false
SKU: LAP0ورقة مرجعية
توفر أدوات الحصول (Getters) والتعيين (Setters) المدمجة مع الحقول الخاصة (private fields) تغليفاً (encapsulation) وتحكماً في الوصول إلى البيانات.
حقل خاص مع أداة الحصول والتعيين
class Temperature {
double _celsius = 0;
double get celsius => _celsius;
set celsius(double value) {
if (value < -273.15) {
_celsius = -273.15;
} else {
_celsius = value;
}
}
}أدوات الحصول المحسوبة (Computed Getters)
يمكن لأدوات الحصول اشتقاق القيم من البيانات الخاصة:
class Rectangle {
double _width;
double _height;
Rectangle(this._width, this._height);
double get area => _width * _height;
double get perimeter => 2 * (_width + _height);
double get width => _width;
set width(double value) {
if (value > 0) _width = value;
}
}وصول للقراءة فقط
قم بتوفير أداة الحصول بدون أداة تعيين للخصائص التي تُقرأ فقط:
class Order {
final DateTime _createdAt = DateTime.now();
DateTime get createdAt => _createdAt;
}جرّب بنفسك
import 'product.dart';
void main() {
// TODO: قم بإنشاء منتج باسم 'Laptop' بسعر 999.99 وكمية 25
// TODO: قم باستدعاء displayProduct()
// TODO: "In stock: [isInStock]" قم بطباعة
// TODO: "SKU: [sku]" قم بطباعة
// TODO: حاول تعيين السعر إلى -50.0 (يجب تجاهله)
// TODO: قم بتعيين السعر إلى 899.99 (تغيير صالح)
// TODO: حاول تعيين الكمية إلى -10 (يجب تجاهله)
// TODO: قم بتعيين الكمية إلى 0 (تغيير صالح)
// TODO: قم باستدعاء displayProduct()
// TODO: "In stock: [isInStock]" قم بطباعة
// TODO: "SKU: [sku]" قم بطباعة
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع