Menu
Coddy logo textTech

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 hanno bisogno di capacità provenienti da più fonti. Un oggetto di gioco potrebbe aver bisogno di muoversi e di 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 aggiunge i propri metodi e la classe finisce per averli 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 che visualizzarsi:

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

Una precauzione: 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

Costruiamo 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 forniti 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 la quantità 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 sia il mixin Attacker sia il mixin 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 del personaggio, un bersaglio da attaccare e una quantità da curare. Crea un Character, mostra il suo stato, fagli attaccare il bersaglio e curarsi, quindi mostra di nuovo il suo stato.

Riceverai cinque input:

  1. Nome del personaggio (una stringa)
  2. Salute iniziale (un numero)
  3. Valore del 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 le abilità di entrambi i 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 fornisce il proprio metodo alla classe Character. Il personaggio non eredita da nessuno dei due mixin. Semplicemente acquisisce le loro abilità tramite la funzione applyMixin. Questa è la potenza della combinazione di più mixin!

Provalo tu

-- File principale

-- TODO: Scrivi 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: Implementa l'applicazione del mixin
end

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

local Character = require('Character')

-- Leggi i dati in ingresso
local name = io.read()
local health = tonumber(io.read())
local damage = tonumber(io.read())
local targetName = io.read()
local healAmount = tonumber(io.read())

-- TODO: Crea un Character con il nome, la salute e il danno indicati

-- TODO: Mostra lo stato del personaggio

-- TODO: Fai attaccare il bersaglio al personaggio

-- TODO: Fai curare il personaggio

-- TODO: Mostra 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