Menu
CoddyTech

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

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

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

הפתרון פשוט: החילו כמה mixins על אותה מחלקה. כל 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

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

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 למשחק שמשלבת יכולות מרובות באמצעות mixins! הדמות שלך תוכל גם לתקוף אויבים וגם לרפא את עצמה: שתי התנהגויות נפרדות שמגיעות מ-mixins נפרדים.

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

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

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

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

הפלט שלך צריך להציג את הדמות משתמשת ביכולות של שני ה-mixins:

{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

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

נסו בעצמכם

-- קובץ ראשי

-- 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 אונליין