استدعاء دوال الفئة الأب
جزء من قسم البرمجة كائنية التوجه في رحلة 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) تشغيل منطق الدالة الأب أولاً، أو آخراً، أو حتى في منتصف الكود الخاص بها، مما يمنحك تحكماً كاملاً في كيفية دمج السلوكيات.
التحدي
سهللنقم ببناء نظام تحية حيث يقوم 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" — بل يفوض هذا العمل لتابع الأب، ثم يضيف سلوكه الفريد الخاص فوقه. هذا يحافظ على نظافة الكود الخاص بك ويوضح كيف يمكن للفئات الفرعية توسيع وظائف الأب بدلاً من استبدالها!
جرّب بنفسك
-- main.lua: نقطة الدخول لنظام التحية
local FormalPerson = require('FormalPerson')
-- قراءة اسم الشخص من المدخلات
local name = io.read()
-- TODO: إنشاء مثيل من FormalPerson بالاسم المعطى
-- TODO: استدعاء الدالة introduce على مثيل FormalPerson
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال