Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الربط باستخدام __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) نظيفة.

challenge icon

التحدي

سهل

الآن دعنا نضع الميثود الوهمي (metamethod) ‏__index قيد التنفيذ! ستقوم بإنشاء نموذج أولي (prototype) وربط مثيل (instance) به، مما يسمح للمثيل بالوصول إلى الخصائص والطرق (methods) التي لا يمتلكها مباشرة.

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • Robot.lua: قم بتعريف جدول النموذج الأولي Robot مع:
    • حقل model مضبوط على "RX-100"
    • حقل batteryLevel مضبوط على 100
    • ميثود :status() يطبع الحالة الحالية للروبوت
    قم بإرجاع الجدول في نهاية الملف.
  • main.lua: اطلب وحدة Robot (Require)، ثم أنشئ جدول مثيل فارغ واربطه بالنموذج الأولي Robot باستخدام setmetatable مع __index. يتيح ذلك لمثيلك الفارغ الوصول إلى كل شيء من النموذج الأولي.

ستتلقى مدخلاً واحداً: اسماً لتعيينه لمثيل الروبوت الخاص بك.

بعد ربط المثيل بالنموذج الأولي:

  1. قم بتعيين الاسم المدخل إلى حقل name الخاص بمثيلك (يصبح هذا فريداً للمثيل)
  2. استدعِ الميثود :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() على الكائن الخاص بك
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming