Menu
Coddy logo textTech

החלת כמה מיקסינים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Lua של Coddy. שיעור 52 מתוך 70.

Mixin יחיד מוסיף קבוצה אחת של התנהגויות למחלקה. אבל אובייקטים אמיתיים זקוקים לעיתים קרובות ליכולות ממקורות מרובים. ייתכן שאובייקט במשחק יצטרך לנוע וגם להיות גלוי על המסך: שתי דאגות נפרדות שלא שייכות לאותו mixin.

הפתרון פשוט: החילו כמה מיקסינים על אותה מחלקה. כל מיקסין תורם את המתודות שלו, ובסופו של דבר למחלקה יש את כולן:

local Movable = {}
function Movable:move(dx, dy)
    self.x = self.x + dx
    self.y = self.y + dy
end

local Visible = {}
function Visible:show()
    print("Showing at " .. self.x .. ", " .. self.y)
end
function Visible:hide()
    print("Hidden")
end

החילו את שני ה-mixins על המחלקה שלכם באמצעות אותה פונקציית עזר כמו קודם:

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

local GameObject = {}
GameObject.__index = GameObject

applyMixin(GameObject, Movable)
applyMixin(GameObject, Visible)

כעת מופעים של GameObject יכולים גם לנוע וגם להציג את עצמם:

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- מוצג במיקום 5, 3

הערה חשובה: אם שתי ערבובות מגדירות שיטה בעלת אותו שם, הערבובה השנייה שתוחל תדרוס את הראשונה. הקפידו על שמות ייחודיים לשיטות בערבובות שלכם כדי למנוע התנהגות בלתי צפויה.

challenge icon

אתגר

קל

בואו נבנה מחלקת Character למשחק, שמשלבת כמה יכולות באמצעות מיקסינים! הדמות שלכם תוכל גם לתקוף אויבים וגם לרפא את עצמה: שתי התנהגויות נפרדות שמגיעות ממיקסינים שונים.

תארגנו את הקוד שלכם בארבעה קבצים:

  • Attacker.lua: צרו מיקסין עם מתודת :attack(targetName) שמדפיסה {self.name} attacks {targetName} for {self.damage} damage! (בהנחה שלאובייקט יש שדות name ו-damage)
  • Healer.lua: צרו מיקסין עם מתודת :heal(amount) שמוסיפה את הכמות אל self.health ומדפיסה {self.name} heals for {amount}. Health: {newHealth}
  • Character.lua: צרו מחלקת Character עם בנאי :new(name, health, damage) ששומר את כל שלוש התכונות. החילו גם את המיקסין Attacker וגם את המיקסין Healer, כך שכל דמות תוכל לתקוף ולרפא. כללו מתודת :status() שמדפיסה {name} - Health: {health}, Damage: {damage}
  • main.lua: כתבו כאן את פונקציית העזר applyMixin. קראו קלטים עבור שם הדמות, בריאות, נזק, מטרה לתקיפה וכמות לריפוי. צרו Character, הציגו את המצב שלה, תקפו את המטרה, רפאו את עצמכם ואז הציגו שוב את המצב שלה.

תקבלו חמישה קלטים:

  1. שם הדמות (מחרוזת)
  2. בריאות התחלתית (מספר)
  3. ערך הנזק (מספר)
  4. שם המטרה לתקיפה (מחרוזת)
  5. כמות לריפוי (מספר)

הפלט שלכם צריך להראות את הדמות משתמשת בשתי היכולות שמספקים המיקסינים:

{name} - Health: {health}, Damage: {damage}
{name} attacks {target} for {damage} damage!
{name} heals for {healAmount}. Health: {newHealth}
{name} - Health: {newHealth}, Damage: {damage}

לדוגמה, אם הקלטים הם Warrior, 100, 25, Goblin ו-30, הפלט צריך להיות:

Warrior - Health: 100, Damage: 25
Warrior attacks Goblin for 25 damage!
Warrior heals for 30. Health: 130
Warrior - Health: 130, Damage: 25

כל מיקסין מוסיף מתודה משלו למחלקת Character. הדמות לא יורשת מאף אחד מהמיקסינים. היא פשוט מקבלת את היכולות שלהם באמצעות הפונקציה applyMixin. זהו הכוח שבשילוב כמה מיקסינים!

נסו בעצמכם

-- הקובץ הראשי

-- TODO: כתבו את פונקציית העזר applyMixin
-- פונקציה זו צריכה להעתיק את כל המתודות מטבלת mixin לטבלת היעד
local function applyMixin(target, mixin)
    -- TODO: ממשו את החלת ה-mixin
end

-- הנגישו את applyMixin באופן גלובלי כדי ש-Character.lua יוכל להשתמש בה
_G.applyMixin = applyMixin

local Character = require('Character')

-- קראו את הקלטים
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: צרו Character עם השם, הבריאות והנזק הנתונים

-- TODO: הציגו את מצב הדמות

-- TODO: גרמו לדמות לתקוף את המטרה

-- TODO: גרמו לדמות לרפא את עצמה

-- TODO: הציגו שוב את מצב הדמות
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Lua אונליין