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

دمج الكائنات

جزء من قسم 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 صيغة النقطة وتستقبل كلا المعاملين كوسطاء. الفرق الجوهري عن الطرق الوصفية الحسابية هو أنك تعمل عادةً مع أنواع مختلطة—كائنك وسلسلة نصية.

challenge icon

التحدي

سهل

لنقم ببناء فئة Title يمكنها الاندماج بشكل طبيعي في تعبيرات السلسلة النصية باستخدام عامل التشغيل ... هذا مفيد عندما تريد دمج الكائنات مع السلاسل النصية بطريقة مقروءة وبديهية — مثل إضافة الألقاب التشريفية أو اللاحقات إلى لقب الشخص.

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

  • Title.lua: قم بتعريف فئة Title الخاصة بك مع حقل text يقوم بتخزين سلسلة اللقب. قم بتضمين منشئ :new(text) وقم بتنفيذ الميثود الوهمي (metamethod) __concat. يجب أن يتعامل الميثود الوهمي الخاص بك مع كلتا الحالتين: عندما تأتي سلسلة نصية قبل الكائن ("prefix" .. obj) وعندما تأتي سلسلة نصية بعده (obj .. "suffix"). يجب أن تدمج النتيجة السلسلة النصية مع نص اللقب بشكل مناسب.
  • main.lua: اطلب وحدة Title الخاصة بك، وقم بإنشاء مثيل (instance) للقب، وقم بتوضيح عملية التسلسل (concatenation) من كلا الاتجاهين.

ستتلقى ثلاثة مدخلات:

  1. نص اللقب (على سبيل المثال، "Engineer")
  2. سلسلة بادئة (prefix) لوضعها قبل اللقب (على سبيل المثال، "Senior ")
  3. سلسلة لاحقة (suffix) لوضعها بعد اللقب (على سبيل المثال، " III")

في ملفك الرئيسي، قم بإنشاء Title بالنص المعطى. ثم قم بإجراء عمليتي تسلسل واطبع كل نتيجة في سطر منفصل:

  1. قم بتسلسل سلسلة البادئة مع كائن اللقب
  2. قم بتسلسل كائن اللقب مع سلسلة اللاحقة

على سبيل المثال، إذا كانت المدخلات هي 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 وطباعة النتيجة
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming