وراثة الـ 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. يعني وراثة الدوال التلقائية هذه أنك تكتب السلوك المشترك مرة واحدة في الصنف الأب، ويستفيد كل صنف ابن منه على الفور.
التحدي
سهللنقم ببناء تسلسل هرمي بسيط للكائنات لرؤية وراثة الدوال (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 من buddy ← Dog ← Animal حتى يتم العثور على الدالة.
تنظيم الفئات في ملفات متعددة
ملف الفئة الأب (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() على كائن الكلب
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال