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

استدعاء دوال الفئة الأب

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

أحياناً لا يكون تجاوز الطريقة (method) بالكامل هو ما تريده. بدلاً من ذلك، قد ترغب في توسيع سلوك الأب — تنفيذ ما يفعله الأب، ثم إضافة شيء إضافي. ولتحقيق ذلك، يمكنك استدعاء طريقة الأب مباشرة من داخل عملية التجاوز في الابن.

تستخدم هذه التقنية صيغة النقطة مع اسم الفئة الأب، مع تمرير self كوسيط أول بشكل صريح:

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

-- Dog يوسع سلوك الأب
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    Animal.speak(self)  -- استدعاء دالة الأب أولاً
    print(self.name .. " wags tail happily")
end

السطر الرئيسي هو Animal.speak(self). باستخدام صيغة النقطة على الفئة الأب وتمرير self يدويًا، نقوم باستدعاء الطريقة الأصلية قبل إضافة سلوكنا الخاص:

local buddy = Dog:new("Buddy")
buddy:speak()
-- المخرجات:
-- Buddy يصدر صوتًا
-- Buddy يهز ذيله بسعادة

هذا النمط مفيد عندما تؤدي الدالة الأب (parent method) عملاً هاماً لا ترغب في تكراره. يمكن للدالة الابنة (child) تشغيل منطق الدالة الأب أولاً، أو آخراً، أو حتى في منتصف الكود الخاص بها، مما يمنحك تحكماً كاملاً في كيفية دمج السلوكيات.

challenge icon

التحدي

سهل

لنقم ببناء نظام تحية حيث يقوم FormalPerson بتوسيع سلوك Person العادي! بدلاً من استبدال طريقة تعريف الشخص لنفسه تماماً، ستقوم النسخة الرسمية أولاً بالتعريف القياسي، ثم تضيف لمسة أدب إضافية.

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

  • Person.lua: الفئة الأساسية (base class) الخاصة بك مع منشئ :new(name) يقوم بتخزين اسم الشخص. قم بتضمين تابع :introduce() يطبع اسم الشخص متبوعاً بـ says hi. هذا هو السلوك الأساسي الذي سيتم توسيعه.
  • FormalPerson.lua: فئة فرعية ترث من Person. يجب أن يستدعي المنشئ الخاص بها منشئ الفئة الأب للتعامل مع الاسم. قم بإعادة تعريف (Override) التابع :introduce()، ولكن بدلاً من استبدال سلوك الأب بالكامل، استدعِ تابع الأب أولاً باستخدام Person.introduce(self)، ثم اطبع سطراً إضافياً يحتوي على اسم الشخص متبوعاً بـ bows politely.
  • main.lua: قم باستيراد وحدة FormalPerson، واقرأ اسماً من المدخلات، وأنشئ مثيلاً (instance) من FormalPerson، واستدعِ :introduce() لرؤية السلوكين معاً.

ستتلقى مدخلاً واحداً: اسم الشخص.

عندما تستدعي :introduce() على FormalPerson، يجب أن ينتج سطرين من المخرجات — الأول من تابع الأب، والثاني من إضافة الابن:

{name} says hi
{name} bows politely

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

Eleanor says hi
Eleanor bows politely

الفكرة الأساسية هنا هي أن FormalPerson لا يكرر منطق "says hi" — بل يفوض هذا العمل لتابع الأب، ثم يضيف سلوكه الفريد الخاص فوقه. هذا يحافظ على نظافة الكود الخاص بك ويوضح كيف يمكن للفئات الفرعية توسيع وظائف الأب بدلاً من استبدالها!

ورقة مرجعية

لتوسيع سلوك دالة (method) من الفئة الأب بدلاً من تجاوزها بالكامل، قم باستدعاء دالة الأب من داخل دالة الابن التي تتجاوزها باستخدام صيغة النقطة وتمرير self بشكل صريح:

function ChildClass:method()
    ParentClass.method(self)  -- استدعاء دالة الأب
    -- إضافة سلوك إضافي
end

مثال كامل يوضح توسيع الدالة:

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

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

function Dog:new(name)
    local obj = Animal.new(Animal, name)
    setmetatable(obj, Dog)
    return obj
end

function Dog:speak()
    Animal.speak(self)  -- تنفيذ سلوك الأب أولاً
    print(self.name .. " wags tail happily")  -- إضافة سلوك الابن
end

local buddy = Dog:new("Buddy")
buddy:speak()
-- المخرجات:
-- Buddy makes a sound
-- Buddy wags tail happily

يمكن استدعاء دالة الأب في أي نقطة: قبل، أو بعد، أو في منتصف منطق الابن الخاص، مما يمنح تحكماً كاملاً في كيفية دمج السلوكيات.

جرّب بنفسك

-- main.lua: نقطة الدخول لنظام التحية

local FormalPerson = require('FormalPerson')

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

-- TODO: إنشاء مثيل من FormalPerson بالاسم المعطى

-- TODO: استدعاء الدالة introduce على مثيل FormalPerson
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming