نسخ مستقلة
جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 10 من 70.
يعد أحد الجوانب الحاسمة في البرمجة كائنية التوجه هو أن كل مثيل (instance) يحتفظ بحالته المنفصلة الخاصة به. فعندما تقوم بإنشاء كائنين من نفس الفئة (class)، فإنهما يكونان مستقلين تماماً—تغيير أحدهما لا يؤثر على الآخر.
تأمل هذا المثال:
local Counter = {}
Counter.__index = Counter
function Counter:new(start)
local instance = {}
setmetatable(instance, self)
instance.value = start or 0
return instance
end
function Counter:increment()
self.value = self.value + 1
end
-- إنشاء عدادين منفصلين
local counterA = Counter:new(10)
local counterB = Counter:new(5)
counterA:increment()
counterA:increment()
print(counterA.value) -- المخرجات: 12
print(counterB.value) -- المخرجات: 5على الرغم من أن كلا العدادين يأتيان من نفس الفئة Counter، فإن زيادة counterA ليس لها أي تأثير على counterB. كل كائن له حقل value الخاص به والمخزن في جدول المثيل (instance table) الخاص به.
هذا الاستقلال هو ما يجعل الكائنات مفيدة. يمكنك إنشاء العشرات من اللاعبين في لعبة ما، حيث يتتبع كل منهم صحته ونتيجته الخاصة. يمكنك إدارة حسابات بنكية متعددة، لكل منها رصيد مختلف.
تحدد الفئة (class) الهيكل والسلوك، ولكن كل نسخة (instance) تعيش حياتها الخاصة ببياناتها الخاصة.
التحدي
سهلدعنا نثبت أن الكائنات (objects) من نفس الفئة (class) تعيش حقاً حياة مستقلة! ستقوم ببناء فئة Wallet وإنشاء مثيلين (instances) منفصلين للمحفظة، ثم تعديلهما بشكل مستقل لإثبات أن التغييرات في أحدهما لا تؤثر على الآخر.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Wallet.lua: قم بتعريف فئةWalletالخاصة بك باستخدام نمط المنشئ (constructor) القياسي. يجب أن تتبع كل محفظة رصيدها الخاصbalance. قم بتضمين:- منشئ
:new(startingBalance)يقوم بتهيئة المحفظة بالمبلغ المعطى - طريقة
:add(amount)تزيد الرصيد - طريقة
:spend(amount)تنقص الرصيد
- منشئ
main.lua: اطلب وحدة Wallet الخاصة بك وقم بإنشاء مثيلين منفصلين للمحفظة. قم بإجراء عمليات مختلفة على كل منهما لإظهار أنهما يحافظان على حالة مستقلة.
ستتلقى أربعة مدخلات:
- رصيد البداية للمحفظة A
- رصيد البداية للمحفظة B
- المبلغ المراد إضافته إلى المحفظة A
- المبلغ المراد إنفاقه من المحفظة B
في ملفك الرئيسي:
- قم بإنشاء
walletAبرصيد البداية الأول - قم بإنشاء
walletBبرصيد البداية الثاني - أضف المبلغ المحدد إلى
walletA - أنفق المبلغ المحدد من
walletB - اطبع كلا الرصيدين في سطرين منفصلين
اطبع الأرصدة النهائية بهذا التنسيق الدقيق:
Wallet A: [balance]
Wallet B: [balance]على سبيل المثال، إذا كانت المدخلات هي 100، و 50، و 25، و 10، فيجب أن يكون المخرج:
Wallet A: 125
Wallet B: 40لاحظ كيف أن الإضافة إلى المحفظة A لا تغير المحفظة B، والإنفاق من المحفظة B لا يؤثر على المحفظة A — فكل مثيل يحافظ على رصيده المنفصل.
ورقة مرجعية
يحتفظ كل مثيل من الفئة بحالته المنفصلة الخاصة به. يؤدي إنشاء كائنات متعددة من نفس الفئة إلى الحصول على مثيلات مستقلة تمامًا—تعديل أحدها لا يؤثر على الآخرين.
مثال يوضح استقلالية المثيلات:
local Counter = {}
Counter.__index = Counter
function Counter:new(start)
local instance = {}
setmetatable(instance, self)
instance.value = start or 0
return instance
end
function Counter:increment()
self.value = self.value + 1
end
-- إنشاء عدادين منفصلين
local counterA = Counter:new(10)
local counterB = Counter:new(5)
counterA:increment()
counterA:increment()
print(counterA.value) -- المخرجات: 12
print(counterB.value) -- المخرجات: 5لكل كائن جدول مثيل خاص به يخزن بياناته الخاصة. تحدد الفئة الهيكل والسلوك، لكن كل مثيل يحافظ على حالة مستقلة.
جرّب بنفسك
-- استدعاء وحدة المحفظة (Wallet)
local Wallet = require('Wallet')
-- قراءة المدخلات
local startingA = tonumber(io.read())
local startingB = tonumber(io.read())
local addAmount = tonumber(io.read())
local spendAmount = tonumber(io.read())
-- TODO: إنشاء walletA برصيد البداية الأول
-- TODO: إنشاء walletB برصيد البداية الثاني
-- TODO: إضافة المبلغ المحدد إلى walletA
-- TODO: خصم المبلغ المحدد من walletB
-- TODO: طباعة الأرصدة النهائية بالتنسيق المطلوب
-- التنسيق: "Wallet A: [balance]" و "Wallet B: [balance]"
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال