الربط باستخدام __index
جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 7 من 70.
لديك جدول نموذج أولي (prototype table) يحتوي على خصائص وطرق، ولكن كيف تجعل كائناً جديداً يستخدمه بالفعل؟ تكمن الإجابة في الطريقة الوصفية (metamethod) المسماة __index.
عندما تصل إلى مفتاح غير موجود في جدول، فإن Lua عادةً ما تعيد nil. ومع ذلك، إذا كان للجدول جدول وصفي (metatable) يحتوي على حقل __index، فستبحث Lua هناك بدلاً من ذلك. من خلال تعيين __index ليشير إلى النموذج الأولي (prototype) الخاص بك، يتم العثور تلقائيًا على أي مفاتيح مفقودة في النموذج الأولي:
local Dog = {
species = "Canis familiaris",
legs = 4
}
function Dog:bark()
print("Woof!")
end
-- إنشاء مثيل فارغ
local myDog = {}
-- ربطه بالنموذج الأولي
setmetatable(myDog, { __index = Dog })
print(myDog.species) -- Output: Canis familiaris
myDog:bark() -- Output: Woof!الجدول myDog فارغ تماماً، ومع ذلك فإن الوصول إلى myDog.species يعمل. عندما لا يجد Lua species في myDog، فإنه يتحقق من __index الخاص بالـ metatable ويجده في Dog.
هذا هو أساس البرمجة كائنية التوجه في Lua. يمكن أن يمتلك المثيل (instance) بياناته الفريدة الخاصة، بينما يكمن السلوك المشترك في النموذج الأولي (prototype). في الدرس القادم، ستتعلم كيفية تغليف هذا النمط في دالة منشئ (constructor function) نظيفة.
التحدي
سهلالآن دعنا نضع الميثود الوهمي (metamethod) __index قيد التنفيذ! ستقوم بإنشاء نموذج أولي (prototype) وربط مثيل (instance) به، مما يسمح للمثيل بالوصول إلى الخصائص والطرق (methods) التي لا يمتلكها مباشرة.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Robot.lua: قم بتعريف جدول النموذج الأوليRobotمع:- حقل
modelمضبوط على"RX-100" - حقل
batteryLevelمضبوط على100 - ميثود
:status()يطبع الحالة الحالية للروبوت
- حقل
main.lua: اطلب وحدة Robot (Require)، ثم أنشئ جدول مثيل فارغ واربطه بالنموذج الأولي Robot باستخدامsetmetatableمع__index. يتيح ذلك لمثيلك الفارغ الوصول إلى كل شيء من النموذج الأولي.
ستتلقى مدخلاً واحداً: اسماً لتعيينه لمثيل الروبوت الخاص بك.
بعد ربط المثيل بالنموذج الأولي:
- قم بتعيين الاسم المدخل إلى حقل
nameالخاص بمثيلك (يصبح هذا فريداً للمثيل) - استدعِ الميثود
:status()على مثيلك
يجب أن يطبع الميثود :status() بهذا التنسيق الدقيق:
[name] ([model]) - Battery: [batteryLevel]%على سبيل المثال، إذا كان المدخل هو Sparky، يجب أن يكون المخرج:
Sparky (RX-100) - Battery: 100%لاحظ كيف يمتلك المثيل name الخاص به، ولكنه يصل إلى model و batteryLevel من النموذج الأولي من خلال رابط __index.
ورقة مرجعية
تسمح الطريقة الوصفية (metamethod) المسماة __index للكائنات بوراثة الخصائص والأساليب من جدول النموذج الأولي (prototype table).
عندما تحاول الوصول إلى مفتاح غير موجود في جدول ما، تتحقق لغة Lua مما إذا كان الجدول يحتوي على جدول وصفي (metatable) به حقل __index. إذا كان الأمر كذلك، تبحث Lua عن المفتاح في الجدول المحدد بواسطة __index.
لربط مثيل (instance) بنموذج أولي (prototype):
local Prototype = {
property = "value"
}
function Prototype:method()
print("Method called")
end
-- إنشاء مثيل
local instance = {}
-- الربط بالنموذج الأولي باستخدام __index
setmetatable(instance, { __index = Prototype })
-- الوصول إلى خصائص وأساليب النموذج الأولي
print(instance.property) -- Output: value
instance:method() -- Output: Method calledيمكن أن يكون جدول المثيل فارغاً، ومع ذلك يمكنه الوصول إلى جميع الخصائص والأساليب من النموذج الأولي. يمكن للمثيل أيضاً أن يمتلك خصائصه الفريدة التي تتجاوز أو توسع النموذج الأولي.
هذا النمط هو أساس البرمجة كائنية التوجه (object-oriented programming) في Lua، حيث تتشارك المثيلات السلوك من نموذج أولي مع الحفاظ على بياناتها الفريدة الخاصة.
جرّب بنفسك
-- قراءة المدخلات
local name = io.read()
-- استدعاء وحدة Robot
local Robot = require('Robot')
-- TODO: إنشاء جدول كائن (instance) فارغ
-- TODO: ربط الكائن بنموذج Robot الأولي باستخدام setmetatable مع __index
-- TODO: تعيين الاسم المدخل إلى حقل الاسم الخاص بالكائن
-- TODO: استدعاء الطريقة :status() على الكائن الخاص بك
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال