دمج الكائنات
جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 28 من 70.
يقوم العامل .. في لغة Lua بربط السلاسل النصية، ولكن ماذا لو أردت دمج كائن مع سلسلة نصية؟ تتيح لك الطريقة الوصفية __concat تحديد كيفية عمل ذلك بالضبط.
عندما تواجه Lua التعبير a .. b وكان أحد المعاملات يحتوي على metamethod من النوع __concat، فإنها تستدعي تلك الدالة مع كلتا القيمتين. هذا مفيد عندما تريد أن تندمج الكائنات بشكل طبيعي في تعبيرات السلسلة النصية.
local Name = {}
Name.__index = Name
function Name:new(first, last)
local obj = {first = first, last = last}
setmetatable(obj, Name)
return obj
end
function Name.__concat(a, b)
if type(a) == "string" then
return a .. b.first .. " " .. b.last
else
return a.first .. " " .. a.last .. b
end
endلاحظ أن الدالة تتحقق من أي معامل هو السلسلة النصية. بما أن .. يمكن استخدامها كـ "Hello " .. obj أو obj .. "!"، يجب أن تتعامل الـ metamethod الخاصة بك مع كلتا الحالتين.
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- المخرجات: Dr. Ada Lovelace
print(person .. " PhD") -- المخرجات: Ada Lovelace PhDمثل الطرق الوصفية (metamethods) الأخرى للعمليات، تستخدم __concat صيغة النقطة وتستقبل كلا المعاملين كوسطاء. الفرق الجوهري عن الطرق الوصفية الحسابية هو أنك تعمل عادةً مع أنواع مختلطة—كائنك وسلسلة نصية.
التحدي
سهللنقم ببناء فئة Title يمكنها الاندماج بشكل طبيعي في تعبيرات السلسلة النصية باستخدام عامل التشغيل ... هذا مفيد عندما تريد دمج الكائنات مع السلاسل النصية بطريقة مقروءة وبديهية — مثل إضافة الألقاب التشريفية أو اللاحقات إلى لقب الشخص.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Title.lua: قم بتعريف فئة Title الخاصة بك مع حقلtextيقوم بتخزين سلسلة اللقب. قم بتضمين منشئ:new(text)وقم بتنفيذ الميثود الوهمي (metamethod)__concat. يجب أن يتعامل الميثود الوهمي الخاص بك مع كلتا الحالتين: عندما تأتي سلسلة نصية قبل الكائن ("prefix" .. obj) وعندما تأتي سلسلة نصية بعده (obj .. "suffix"). يجب أن تدمج النتيجة السلسلة النصية مع نص اللقب بشكل مناسب.main.lua: اطلب وحدة Title الخاصة بك، وقم بإنشاء مثيل (instance) للقب، وقم بتوضيح عملية التسلسل (concatenation) من كلا الاتجاهين.
ستتلقى ثلاثة مدخلات:
- نص اللقب (على سبيل المثال، "Engineer")
- سلسلة بادئة (prefix) لوضعها قبل اللقب (على سبيل المثال، "Senior ")
- سلسلة لاحقة (suffix) لوضعها بعد اللقب (على سبيل المثال، " III")
في ملفك الرئيسي، قم بإنشاء Title بالنص المعطى. ثم قم بإجراء عمليتي تسلسل واطبع كل نتيجة في سطر منفصل:
- قم بتسلسل سلسلة البادئة مع كائن اللقب
- قم بتسلسل كائن اللقب مع سلسلة اللاحقة
على سبيل المثال، إذا كانت المدخلات هي Engineer و Senior و III، فيجب أن يكون الناتج:
Senior Engineer
Engineer IIIيوضح السطر الأول البادئة مدمجة مع اللقب، ويوضح السطر الثاني اللقب مدمجاً مع اللاحقة. الميثود الوهمي __concat الخاص بك يجعل هذا الدمج الطبيعي للسلاسل ممكناً!
ورقة مرجعية
تسمح لك الطريقة الوصفية (metamethod) المسماة __concat بتحديد سلوك مخصص لعامل الربط (concatenation operator) .. عند التعامل مع الكائنات.
عندما تصادف لغة Lua التعبير a .. b ويكون لأحد المعاملين طريقة وصفية __concat، فإنها تستدعي تلك الدالة مع كلا القيمتين.
التنفيذ الأساسي
local MyClass = {}
MyClass.__index = MyClass
function MyClass:new(value)
local obj = {value = value}
setmetatable(obj, MyClass)
return obj
end
function MyClass.__concat(a, b)
if type(a) == "string" then
return a .. b.value
else
return a.value .. b
end
endالتعامل مع كلا ترتيبي المعاملات
بما أن .. يمكن استخدامها كـ "string" .. obj أو obj .. "string"، يجب أن تتحقق الطريقة الوصفية الخاصة بك من أي المعاملين هو السلسلة النصية (string) وتتعامل مع كلتا الحالتين:
function Name.__concat(a, b)
if type(a) == "string" then
return a .. b.first .. " " .. b.last
else
return a.first .. " " .. a.last .. b
end
endمثال على الاستخدام
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- Output: Dr. Ada Lovelace
print(person .. " PhD") -- Output: Ada Lovelace PhDمثل الطرق الوصفية الأخرى للعوامل، تستخدم __concat صيغة النقطة (dot syntax) وتستقبل كلا المعاملين كوسيطات (arguments).
جرّب بنفسك
-- قراءة المدخلات
local titleText = io.read()
local prefix = io.read()
local suffix = io.read()
-- استدعاء وحدة Title
local Title = require('Title')
-- TODO: إنشاء مثيل (instance) من Title باستخدام titleText المعطى
-- TODO: دمج prefix مع كائن title وطباعة النتيجة
-- TODO: دمج كائن title مع suffix وطباعة النتيجة
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال