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

Mixins بسيطة

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

يسمح لك التركيب (Composition) بوضع كائنات داخل كائنات أخرى. ولكن ماذا لو كنت تريد مشاركة السلوك عبر أصناف (classes) غير مرتبطة؟

قد يحتاج كل من Player و MenuItem إلى طريقة :describe()، لكنهما لا يشتركان في فئة أب (parent class). هنا يأتي دور الـ mixins.

الـ mixin هو ببساطة جدول يحتوي على دوال. تقوم بـ "خلط" هذه الدوال داخل فئة (class) عن طريق نسخها إليها:

local Printable = {}

function Printable:describe()
    print("Object: " .. tostring(self))
end

function Printable:log(message)
    print("[LOG] " .. message)
end

لتطبيق هذا الـ mixin على class، ستقوم بنسخ كل function من جدول الـ mixin إلى جدول الـ class:

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local Player = {}
Player.__index = Player

applyMixin(Player, Printable)  -- الآن يمتلك Player كلاً من :describe() و :log()

بعد تطبيق الـ mixin، يمكن لأي مثيل لـ Player استدعاء تلك الدوال كما لو كانت مُعرفة مباشرةً في الفئة:

local p = setmetatable({}, Player)
p:log("Player created")  -- [LOG] تم إنشاء اللاعب

على عكس الوراثة، لا تنشئ الـ mixins علاقة أب-ابن. أنت ببساطة تقوم بنسخ الدوال من جدول إلى آخر.

هذا يجعل الـ mixins مثالية لمشاركة سلوكيات الأدوات المساعدة—مثل طرق التسجيل (logging)، أو التسلسل (serialization)، أو الوصف (description)—عبر الفئات (classes) التي ليس بينها أي قاسم مشترك آخر.

challenge icon

التحدي

سهل

لنقم ببناء نظام وسوم (tagging system) باستخدام الـ mixins! ستقوم بإنشاء mixin باسم Taggable يمكن تطبيقه على أي فئة، مما يمنح الكائنات القدرة على إدارة مجموعة من الوسوم — وهو أمر مفيد لتصنيف العناصر، أو المنشورات، أو أي كيان يحتاج إلى تسميات.

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

  • Taggable.lua: أنشئ جدول mixin يحتوي على طريقتين (methods):
    • :addTag(tag) — يضيف وسماً إلى self.tags (يفترض أن الجدول موجود)
    • :listTags() — يطبع جميع الوسوم بالتنسيق Tags: tag1, tag2, tag3 (أو Tags: none إذا كان فارغاً)
  • Article.lua: أنشئ فئة Article مع منشئ :new(title) يقوم بتخزين العنوان ويهيئ جدول tags فارغاً. قم بتطبيق Taggable mixin لمنح مثيلات Article قدرات الوسم. قم بتضمين طريقة :getTitle() التي تعيد عنوان المقال.
  • main.lua: اكتب الدالة المساعدة applyMixin هنا (ستستخدمها في Article.lua عبر require). ثم اقرأ المدخلات لعنوان المقال ووسمين. أنشئ Article، وأضف كلا الوسمين إليه، واطبع العنوان، واعرض قائمة بجميع الوسوم.

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

  1. عنوان المقال (سلسلة نصية)
  2. الوسم الأول المراد إضافته (سلسلة نصية)
  3. الوسم الثاني المراد إضافته (سلسلة نصية)

يجب أن يعرض مخرجك عنوان المقال متبوعاً بوسومه:

Title: {title}
Tags: {tag1}, {tag2}

على سبيل المثال، إذا كانت المدخلات هي Lua Basics، و programming، و tutorial، فيجب أن يكون المخرج:

Title: Lua Basics
Tags: programming, tutorial

تذكر: تعمل طرق الـ mixin لأن مثيلات Article تحتوي على جدول tags يمكن لطرق الـ mixin العمل عليه. الـ mixin لا ينشئ هذا الجدول — بل يقوم منشئ Article الخاص بك بذلك. الـ mixin يوفر فقط السلوك المشترك!

ورقة مرجعية

الـ mixin هو جدول يحتوي على دوال يمكن مشاركتها عبر فئات (classes) غير مرتبطة دون إنشاء علاقة أب-ابن (parent-child).

لإنشاء mixin، قم بتعريف جدول يحتوي على دوال (methods):

local Printable = {}

function Printable:describe()
    print("Object: " .. tostring(self))
end

function Printable:log(message)
    print("[LOG] " .. message)
end

لتطبيق mixin على فئة (class)، قم بنسخ دواله إلى جدول الفئة:

local function applyMixin(class, mixin)
    for key, value in pairs(mixin) do
        class[key] = value
    end
end

local Player = {}
Player.__index = Player

applyMixin(Player, Printable)

بعد تطبيق الـ mixin، يمكن للكائنات (instances) استدعاء دوال الـ mixin:

local p = setmetatable({}, Player)
p:log("Player created")  -- [LOG] Player created

تعد الـ Mixins مثالية لمشاركة سلوكيات الأدوات المساعدة مثل تسجيل الأحداث (logging)، أو التسلسل (serialization)، أو الوسم (tagging) عبر الفئات التي لا تشترك في الوراثة.

جرّب بنفسك

-- الملف الرئيسي لنظام الوسم
local Taggable = require('Taggable')
local Article = require('Article')

-- TODO: تنفيذ دالة applyMixin
-- يجب أن تقوم هذه الدالة بنسخ جميع الأساليب من جدول mixin إلى جدول الهدف
function applyMixin(target, mixin)
    -- TODO: التكرار عبر mixin ونسخ كل أسلوب إلى الهدف
end

-- قراءة المدخلات
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()

-- TODO: إنشاء مقال (Article) بالعنوان المعطى

-- TODO: إضافة كلا الوسمين إلى المقال

-- TODO: طباعة العنوان بالتنسيق: Title: {title}

-- TODO: سرد جميع الأوسمة باستخدام أسلوب listTags
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming