الخصائص المحسوبة
جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 15 من 70.
توفّر دوال Getters وSetters إمكانية الوصول إلى القيم المخزّنة، لكنك تحتاج أحيانًا إلى بيانات غير موجودة كحقل مخزّن. يجب حسابها من سمات أخرى. وتُسمّى هذه الخصائص المحسوبة.
تأمل مستطيلاً. تخزّن عرضه وارتفاعه، لكن المساحة لا تُخزَّن في أي مكان: بل تُحسَب بضرب هاتين القيمتين معًا. وبدلاً من تخزين بيانات زائدة، تنشئ أسلوبًا يحسب النتيجة ويعيدها:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endلا تُرجع الطريقة :getArea() قيمة مخزّنة. بل تحسب area من جديد في كل مرة تستدعيها فيها. يتميّز هذا الأسلوب بميزة أساسية: إذا تغيّرت width أو height، فإن area تعكس dimensions الجديدة تلقائيًا من دون الحاجة إلى تحديث أي شيء.
local box = Rectangle:new(5, 3)
print(box:getArea()) -- المخرجات: 15
box.width = 10
print(box:getArea()) -- المخرجات: 30تحافظ الخصائص المحسوبة على اتساق كائناتك. وبدلًا من تخزين القيم التي تعتمد على حقول أخرى (والمخاطرة بأن تصبح قديمة)، تحسبها عند الطلب. ينطبق هذا النمط على أي بيانات مشتقة: المحيطات، أو المتوسطات، أو السلاسل النصية المنسقة، أو أي قيمة يمكن تحديدها من السمات الموجودة.
التحدي
سهللنبنِ فئة Box تحسب حجمها عند الطلب! بدلاً من تخزين الحجم كحقل، ستنشئ خاصية محسوبة تحسبه من أبعاد الصندوق كلما دعت الحاجة إليها.
ستنظّم التعليمات البرمجية عبر ملفين:
Box.lua: عرّف فئةBoxباستخدام نمطprototypeالقياسي. يخزّن كل صندوق ثلاثة أبعاد:widthوheightوdepth. أدرج:- منشئ
:new(width, height, depth)يخزّن الأبعاد الثلاثة كلها - طريقة
:getVolume()تحسب الحجم وتعيده (العرض × الارتفاع × العمق) - طريقة
:getSurfaceArea()تحسب مساحة السطح الكلية وتعيدها
- منشئ
main.lua: استخدمRequireلوحدة Box، وأنشئ مثيلاً للصندوق، ووضّح كيف تعكس الخصائص المحسوبة الأبعاد الحالية تلقائياً.
تُحسب مساحة سطح الصندوق كما يلي: 2 × (width×height + height×depth + width×depth)
ستتلقى ثلاثة مدخلات تمثل أبعاد الصندوق:
- العرض
- الارتفاع
- العمق
في ملفك الرئيسي، أنشئ صندوقاً بالأبعاد المعطاة، ثم اطبع سطرين:
- الحجم باستخدام
:getVolume() - مساحة السطح باستخدام
:getSurfaceArea()
على سبيل المثال، إذا كانت المدخلات هي 3 و4 و5، فينبغي أن يكون الناتج:
60
94يكمن جمال الخصائص المحسوبة في أنها تظل دقيقة دائماً. إذا غيّرت لاحقاً أحد أبعاد الصندوق، فإن استدعاء :getVolume() مرة أخرى سيعيد تلقائياً القيمة الجديدة الصحيحة: لا حاجة إلى تحديثات يدوية!
جرّب بنفسك
-- استيراد وحدة Box
local Box = require('Box')
-- قراءة أبعاد الإدخال
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())
-- TODO: إنشاء مثيل box بالأبعاد المعطاة
-- TODO: طباعة الحجم باستخدام :getVolume()
-- TODO: طباعة مساحة السطح باستخدام :getSurfaceArea()
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
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 عبر الإنترنت