Menu
CoddyTech

Mixins مقابل الوراثة

جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 53 من 70.

لقد تعلّمت طريقتين لمشاركة السلوك: ينشئ الوراثة علاقة «هو نوع من» عبر سلسلة النموذج الأولي، بينما تنسخ المزائج الدوال مباشرةً إلى فئة. لكن متى ينبغي استخدام كل طريقة؟

استخدم الوراثة عندما تشترك الكائنات في هوية أساسية. Bird هو نوع من Animal. من المنطقي أن يرث Bird السلوكيات الأساسية للحيوانات مثل :eat() أو :sleep(). هذه العلاقة دائمة وتحدد ماهية الكائن في جوهره.

استخدم المزائج عندما تريد إضافة قدرة لا تحدد الهوية الأساسية للكائن.

ليست كل الطيور قادرة على الطيران: فالبطاريق والنعام طيور، لكنها لا تطير. الطيران قدرة، وليس سمة أساسية لتعريف الطائر. يتيح لك المزيج Flyable إضافة القدرة على الطيران إلى الطيور التي تحتاج إليها، من دون فرضها على جميع الطيور.

يعمل النهجان معًا. هنا، يرث كلٌّ من Eagle وPenguin من Bird، ولا يحصل على المزيج إلا Eagle:

-- يرث Bird من Animal (علاقة «هو نوع من»)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

-- كلٌّ من Eagle وPenguin طائر
local Eagle = setmetatable({}, {__index = Bird})
Eagle.__index = Eagle
local Penguin = setmetatable({}, {__index = Bird})
Penguin.__index = Penguin

-- Flyable قدرة (mixin)
local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

-- طبّق الـmixin على الطيور التي تطير فقط
applyMixin(Eagle, Flyable)

يستطيع النسر استدعاء :fly(). أما البطريق فلا يستطيع ذلك: فـfly غير موجودة في Penguin أو Bird أو Animal، لذا فإن penguin:fly() خطأ. أما تطبيق المزيج على Bird بدلًا من ذلك فسينسخ fly إلى كل طائر، بما في ذلك طيور البطريق.

challenge icon

التحدي

سهل

لنبنِ نظامًا بيئيًا صغيرًا من الكائنات يوضّح متى نستخدم الوراثة ومتى نستخدم الخلطات! ستنشئ فئة أساسية Animal، وفئة Bird ترث منها، وخلطة Swimmable، لأنه مع أن جميع الطيور حيوانات، فليس بإمكان جميع الطيور السباحة.

ستنظّم شيفرتك على أربعة ملفات:

  • Animal.lua: أنشئ الفئة الأساسية Animal مع مُنشئ :new(name) يخزّن الاسم. أضف طريقة :eat() تطبع {name} is eating. يمثّل هذا الهوية الأساسية المشتركة بين جميع الحيوانات.
  • Swimmable.lua: أنشئ خلطة تتضمن طريقة :swim() تطبع {self.name} is swimming. هذه قدرة، وليست كل الكائنات قادرة على السباحة، لذا لا ينبغي أن تكون جزءًا من سلسلة الوراثة.
  • Bird.lua: أنشئ فئة Bird ترث من Animal. ينبغي أن يستدعي المُنشئ :new(name) مُنشئ الفئة الأب. أضف طريقة :chirp() تطبع {name} chirps!. هذا سلوك خاص بالطيور. لا تضف السباحة إلى Bird: فليس بإمكان كل الطيور السباحة.
  • main.lua: اكتب الدالة المساعدة applyMixin(target, mixin) هنا: فهي تنسخ كل دوال الخلطة إلى الهدف. اقرأ اسم الطائر وما إذا كان بإمكانه السباحة (yes أو no). أنشئ طائرًا من فئة Bird، وإذا كان بإمكانه السباحة، فأضف خلطة Swimmable إلى ذلك الطائر وحده. ثم استدعِ :eat() (الموروثة من Animal) و:chirp() (الطريقة الخاصة بفئة Bird)، واستدعِ :swim() فقط إذا كانت هذه الطريقة متاحة لهذا الطائر (if bird.swim then).

ستتلقى مُدخلين:

  1. اسم الطائر (سلسلة نصية)
  2. ما إذا كان بإمكان الطائر السباحة: yes أو no

إذا كان بإمكان الطائر السباحة، فينبغي أن يكون الناتج:

{name} is eating
{name} chirps!
{name} is swimming

إذا لم يكن بإمكان الطائر السباحة، فينبغي أن يكون الناتج:

{name} is eating
{name} chirps!

على سبيل المثال، إذا كان المُدخلان Duck وyes، فينبغي أن يكون الناتج:

Duck is eating
Duck chirps!
Duck is swimming

إذا كان المُدخلان Sparrow وno، فينبغي أن يكون الناتج:

Sparrow is eating
Sparrow chirps!

يوضّح هذا التحدي الفرق الأساسي: الطائر هو حيوان (وراثة)، لكن السباحة قدرة اختيارية (خلطة). ولأن الخلطة تُضاف إلى الطيور القادرة على السباحة فقط، فلا تكون لدى الطائر الذي لا يستطيع السباحة طريقة swim على الإطلاق.

جرّب بنفسك

-- main.lua: نقطة الدخول - أنشئ طائرًا واستعرض قدراته

-- دالة مساعدة لتطبيق mixin على صنف أو كائن واحد
local function applyMixin(target, mixin)
    -- TODO: انسخ كل دالة من mixin إلى target

end

local Bird = require('Bird')
local Swimmable = require('Swimmable')

-- اقرأ المدخلات
local name = io.read()
local canSwimInput = io.read()

-- TODO: أنشئ مثيلًا من Bird بالاسم

-- TODO: إذا كانت قيمة الإدخال "yes"، فطبّق mixin ‏Swimmable على هذا الطائر فقط

-- TODO: استدعِ eat() - الموروثة من Animal

-- TODO: استدعِ chirp() - الدالة الخاصة بـ Bird

-- TODO: استدعِ swim() فقط إذا كان هذا الطائر يملكها
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Lua عبر الإنترنت