الوصول عبر Closures
جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 45 من 70.
تكون متغيرات private local عديمة الفائدة إذا لم تتمكن من التفاعل معها مطلقًا. والحل هو Define getter وsetter methods inside the constructor، حيث يمكنها الوصول إلى نطاق closure.
بما أن هذه methods تُنشأ داخل :new()، فيمكنها الوصول إلى المتغيرات local. وتُسندها مباشرةً إلى الكائن:
local Counter = {}
Counter.__index = Counter
function Counter:new()
local count = 0 -- متغير خاص
local obj = {}
-- تعريف الدوال داخل المُنشئ
function obj:getCount()
return count
end
function obj:increment()
count = count + 1
end
setmetatable(obj, Counter)
return obj
endيمكن الآن الوصول إلى المتغير الخاص count، ولكن فقط من خلال methods التي توفرها:
local c = Counter:new()
print(c:getCount()) -- 0
c:increment()
c:increment()
print(c:getCount()) -- 2
print(c.count) -- nil (ما زال مخفياً!)لاحظ أن :getCount() و:increment() مُعرَّفان على obj مباشرةً، وليس على جدول class. يحصل كل instance على نسخته الخاصة من هذه الدوال، مع وصول كل نسخة إلى count الخاص بها. هذه هي المفاضلة: تتطلب الخصوصية الحقيقية قدرًا أكبر قليلًا من الذاكرة، لأن methods لا تتم مشاركتها عبر النموذج الأولي.
التحدي
سهللنبنِ Temperature class تستخدم الخصوصية القائمة على closure لتخزين قيمة درجة الحرارة بوحدة Celsius، مع تعريف methods getter وsetter داخل constructor لتوفير وصول مُتحكَّم به!
ستنظّم كودك عبر ملفين:
Temperature.lua: أنشئ class تُخزَّن فيها قيمة درجة الحرارة في متغير local داخل constructor: مخفية تمامًا عن الوصول الخارجي. يجب أن يخزّن constructor:new(initialCelsius)درجة الحرارة في متغير local، ثم يعرّف هذه methods مباشرة على instance الكائن::getCelsius(): يعيد درجة الحرارة الحالية بوحدة Celsius:setCelsius(value): يحدّث درجة الحرارة إلى قيمة جديدة:getFahrenheit(): يعيد درجة الحرارة converted إلى Fahrenheit باستخدام Formula:(celsius * 9/5) + 32
main.lua: استخدم require لوحدة Temperature واقرأ قيمتين من input: درجة حرارة initial ودرجة حرارة جديدة لضبطها. أنشئ instance من Temperature باستخدام القيمة initial، واطبع قراءات Celsius وFahrenheit، ثم استخدم setter لتغيير درجة الحرارة واطبع القراءتين كلتيهما مرة أخرى.
ستتلقى inputين:
- درجة الحرارة initial بوحدة Celsius (رقم)
- درجة حرارة جديدة لضبطها (رقم)
يجب أن يتكون output الخاص بك من أربعة أسطر تعرض قراءات درجة الحرارة قبل change وبعدها:
Celsius: {initialValue}
Fahrenheit: {convertedInitial}
Celsius: {newValue}
Fahrenheit: {convertedNew}على سبيل المثال، إذا كانت قيمتا input هما 0 و100، فيجب أن يكون output كما يلي:
Celsius: 0
Fahrenheit: 32
Celsius: 100
Fahrenheit: 212تذكّر: يجب تخزين قيمة درجة الحرارة في متغير local داخل :new()، وليس على self. يتم تعريف methods getter وsetter داخل constructor، حيث يمكنها الوصول إلى هذا المتغير private من خلال closure. يجب أن تؤدي محاولة الوصول إلى temp.celsius أو temp._celsius مباشرةً إلى إرجاع nil!
جرّب بنفسك
-- استيراد وحدة Temperature
local Temperature = require('Temperature')
-- اقرأ قيم الإدخال
local initialTemp = tonumber(io.read())
local newTemp = tonumber(io.read())
-- TODO: أنشئ كائن Temperature بالقيمة الأولية
-- TODO: اطبع قراءات Celsius و Fahrenheit الأولية
-- TODO: استخدم الـ setter لتغيير درجة الحرارة إلى newTemp
-- TODO: اطبع قراءات Celsius و Fahrenheit المحدّثة
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكالتدرّب بنفسك: مترجم Lua عبر الإنترنت