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

وراثة الـ Methods

جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 32 من 70.

بمجرد إنشاء رابط الوراثة، تكتسب مثيلات الفئة الفرعية (child class instances) تلقائيًا إمكانية الوصول إلى جميع أساليب الفئة الأصلية (parent methods). يحدث هذا من خلال سلسلة البحث (lookup chain) الخاصة بـ Lua—فعندما تستدعي أسلوبًا (method) على مثيل (instance)، تبحث Lua عبر كل جدول متصل حتى تجد ما تبحث عنه.

تأمل هذا الإعداد حيث يُعرّف Animal دالة :breathe():

local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

-- Dog يرث من Animal
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new()
    local obj = {}
    setmetatable(obj, Dog)
    return obj
end

الآن شاهد ما يحدث عندما ننشئ Dog ونستدعي دالة الفئة الأب:

local buddy = Dog:new()
buddy:breathe()  -- الناتج: يتنفس...

لم يقم صنف Dog أبدًا بتعريف :breathe()، ومع ذلك فهو يعمل. تقوم Lua أولاً بفحص buddy ولا تجد شيئاً، ثم تفحص Dog ولا تجد شيئاً أيضاً، وأخيراً تجده في Animal. يعني وراثة الدوال التلقائية هذه أنك تكتب السلوك المشترك مرة واحدة في الصنف الأب، ويستفيد كل صنف ابن منه على الفور.

challenge icon

التحدي

سهل

لنقم ببناء تسلسل هرمي بسيط للكائنات لرؤية وراثة الدوال (methods) قيد التنفيذ! ستقوم بإنشاء فئة أب Animal وفئة ابن Dog، ثم توضح أن مثيلات Dog يمكنها استخدام الدوال المعرفة فقط في Animal.

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

  • Animal.lua: قم بتعريف فئة الأب باستخدام نمط الفئات القياسي. قم بتضمين منشئ :new(name) يقوم بتخزين اسم الحيوان، ودالة :speak() تطبع اسم الحيوان متبوعاً بـ makes a sound. قم بإرجاع الفئة في نهاية الملف.
  • Dog.lua: قم بتعريف فئة الابن التي ترث من Animal. اطلب وحدة Animal وقم بإعداد رابط الوراثة بحيث يمكن لـ Dog الوصول إلى دوال Animal. قم بتضمين منشئ :new(name) يقوم بتخزين الاسم وتعيين Dog كـ metatable. يجب ألا تقوم فئة Dog بتعريف دالة :speak() الخاصة بها — بل سترثها من Animal.
  • main.lua: اطلب وحدة Dog الخاصة بك، واقرأ اسماً من الإدخال، وأنشئ مثيلاً من Dog بهذا الاسم، واستدعِ دالة :speak() عليه.

ستتلقى مدخلاً واحداً: اسم الكلب.

على سبيل المثال، إذا كان الإدخال هو Buddy، يجب أن يكون المخرج:

Buddy makes a sound

السحر هنا هو أن فئة Dog الخاصة بك لا تقوم أبداً بتعريف :speak()، ومع ذلك فإن استدعاءها على مثيل Dog يعمل بشكل مثالي. تتبع Lua سلسلة البحث من مثيل Dog إلى فئة Dog، ثم إلى فئة Animal حيث تجد الدالة. هذه هي الوراثة في أبهى صورها!

ورقة مرجعية

تكتسب مثيلات الفئة الفرعية (Child class) تلقائياً إمكانية الوصول إلى جميع دوال الفئة الأب (Parent class) من خلال سلسلة البحث في Lua. عندما يتم استدعاء دالة على مثيل ما، تبحث Lua عبر كل جدول متصل حتى تجد الدالة.

إعداد الوراثة

تعريف الفئة الأب:

local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

الفئة الفرعية مع رابط الوراثة:

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new()
    local obj = {}
    setmetatable(obj, Dog)
    return obj
end

استخدام الدوال الموروثة

يمكن لمثيلات الفئة الفرعية استدعاء دوال الفئة الأب حتى لو لم تكن معرفة في الفئة الفرعية:

local buddy = Dog:new()
buddy:breathe()  -- Output: Breathing...

سلسلة البحث: تتحقق Lua من buddyDogAnimal حتى يتم العثور على الدالة.

تنظيم الفئات في ملفات متعددة

ملف الفئة الأب (Animal.lua):

local Animal = {}
Animal.__index = Animal

function Animal:new(name)
    local obj = {name = name}
    setmetatable(obj, Animal)
    return obj
end

function Animal:speak()
    print(self.name .. " makes a sound")
end

return Animal

ملف الفئة الفرعية (Dog.lua):

local Animal = require("Animal")

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = {name = name}
    setmetatable(obj, Dog)
    return obj
end

return Dog

الاستخدام في الملف الرئيسي:

local Dog = require("Dog")
local buddy = Dog:new("Buddy")
buddy:speak()  -- Output: Buddy makes a sound

جرّب بنفسك

-- main.lua: نقطة الدخول

local Dog = require('Dog')

-- قراءة اسم الكلب من المدخلات
local name = io.read()

-- TODO: إنشاء كائن Dog بالاسم المعطى

-- TODO: استدعاء الدالة :speak() على كائن الكلب
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming