Menu
CoddyTech

Applicare più mixin

Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 52 di 70.

Un singolo mixin aggiunge un insieme di comportamenti a una classe. Ma gli oggetti reali spesso necessitano di capacità provenienti da più fonti. Un oggetto di gioco potrebbe dover muoversi e essere visibile sullo schermo: due aspetti distinti che non dovrebbero appartenere allo stesso mixin.

La soluzione è semplice: applica più mixin alla stessa classe. Ogni mixin contribuisce con i propri metodi e la classe si ritrova con tutti:

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

Applica entrambi i mixin alla tua classe usando la stessa funzione helper di prima:

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)

Ora le istanze di GameObject possono sia muoversi sia visualizzarsi:

local obj = setmetatable({x = 0, y = 0}, GameObject)
obj:move(5, 3)
obj:show()  -- Visualizzazione a 5, 3

Un'avvertenza: se due mixin definiscono un metodo con lo stesso nome, il secondo applicato sovrascriverà il primo. Mantieni distinti i metodi dei tuoi mixin per evitare comportamenti imprevisti.

challenge icon

Sfida

Facile

Creiamo una classe Character per un gioco che combina più capacità usando i mixin! Il tuo personaggio potrà sia attaccare i nemici sia curarsi: due comportamenti distinti che derivano da mixin separati.

Organizzerai il codice in quattro file:

  • Attacker.lua: crea un mixin con un metodo :attack(targetName) che stampa {self.name} attacks {targetName} for {self.damage} damage! (presuppone che l'oggetto abbia i campi name e damage)
  • Healer.lua: crea un mixin con un metodo :heal(amount) che aggiunge l'importo a self.health e stampa {self.name} heals for {amount}. Health: {newHealth}
  • Character.lua: crea una classe Character con un costruttore :new(name, health, damage) che memorizza tutti e tre gli attributi. Applica entrambi i mixin Attacker e Healer, così ogni personaggio può attaccare e curarsi. Includi un metodo :status() che stampa {name} - Health: {health}, Damage: {damage}
  • main.lua: scrivi qui la funzione helper applyMixin. Leggi gli input per il nome, la salute e il danno di un personaggio, un bersaglio da attaccare e un valore di cura. Crea un Character, mostra il suo stato, fagli attaccare il bersaglio e curarsi, poi mostra di nuovo il suo stato.

Riceverai cinque input:

  1. Nome del personaggio (una stringa)
  2. Salute iniziale (un numero)
  3. Valore di danno (un numero)
  4. Nome del bersaglio da attaccare (una stringa)
  5. Quantità da curare (un numero)

L'output dovrebbe mostrare il personaggio mentre usa entrambe le abilità dei mixin:

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

Per esempio, se gli input sono Warrior, 100, 25, Goblin e 30, l'output dovrebbe essere:

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

Ogni mixin aggiunge il proprio metodo alla classe Character. Il personaggio non eredita da nessuno dei due mixin. Acquisisce semplicemente le loro abilità tramite la funzione applyMixin. Questa è la potenza della combinazione di più mixin!

Provalo tu

-- File principale

-- TODO: Scrivere la funzione di supporto applyMixin
-- Questa funzione deve copiare tutti i metodi da una tabella mixin a una tabella di destinazione
local function applyMixin(target, mixin)
    -- TODO: Implementare l'applicazione del mixin
end

-- Rendere applyMixin disponibile globalmente affinché Character.lua possa usarla
_G.applyMixin = applyMixin

local Character = require('Character')

-- Leggere gli input
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: Creare un Character con il nome, la salute e il danno specificati

-- TODO: Mostrare lo stato del personaggio

-- TODO: Far attaccare il bersaglio al personaggio

-- TODO: Far curare il personaggio

-- TODO: Mostrare di nuovo lo stato del personaggio
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Lua online