Menu
Coddy logo textTech

Mixin vs ereditarietà

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

Hai imparato due modi per condividere il comportamento: l'ereditarietà crea una relazione «è un» attraverso la catena dei prototipi, mentre i mixin copiano le funzioni direttamente in una classe. Ma quando dovresti usare ciascun approccio?

Usa l'ereditarietà quando gli oggetti condividono un'identità fondamentale. Un Bird è un Animal. Ha senso che Bird erediti comportamenti fondamentali degli animali come :eat() o :sleep(). La relazione è permanente e definisce ciò che l'oggetto è fondamentalmente.

Usa i mixins quando vuoi aggiungere una capacità che non definisce l’identità fondamentale dell’oggetto.

Non tutti gli uccelli possono volare: i pinguini e gli struzzi sono uccelli, ma non volano. Volare è una capacità, non una caratteristica distintiva dell'essere un uccello. Un mixin Flyable ti permette di aggiungere la capacità di volare agli uccelli che ne hanno bisogno, senza imporla a tutti.

I due approcci funzionano benissimo insieme:

-- Bird eredita da Animal (relazione «è un»)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

-- Flyable è una capacità (mixin)
local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

-- Applica il mixin solo agli uccelli che possono volare
applyMixin(Bird, Flyable)

Questo schema ti offre il meglio di entrambi i mondi: una gerarchia di classi chiara per un’identità condivisa, più capacità flessibili che possono essere combinate quando necessario.

challenge icon

Sfida

Facile

Costruiamo un piccolo ecosistema di creature che mostri quando usare l'ereditarietà invece dei mixin! Creerai una classe base Animal, una classe Bird che eredita da essa e un mixin Swimmable, perché, sebbene tutti gli uccelli siano animali, non tutti gli uccelli sanno nuotare.

Organizzerai il codice in quattro file:

  • Animal.lua: crea la classe base Animal con un costruttore :new(name) che memorizza il nome. Includi un metodo :eat() che stampa {name} is eating. Questo rappresenta l'identità fondamentale condivisa da tutti gli animali.
  • Swimmable.lua: crea un mixin con un metodo :swim() che stampa {self.name} is swimming. Questa è una capacità: non tutte le creature sanno nuotare, quindi non dovrebbe far parte della catena di ereditarietà.
  • Bird.lua: crea una classe Bird che eredita da Animal. Il costruttore :new(name, canSwim) dovrebbe chiamare il costruttore della classe genitore e memorizzare se questo uccello sa nuotare. Applica il mixin Swimmable alla classe Bird. Includi un metodo :chirp() che stampa {name} chirps!. Questo è un comportamento specifico degli uccelli.
  • main.lua: scrivi qui la funzione di supporto applyMixin. Leggi gli input relativi al nome dell'uccello e alla possibilità che sappia nuotare (yes o no). Crea un'istanza di Bird, quindi mostra le sue capacità: chiama :eat() (ereditato da Animal), chiama :chirp() (metodo proprio di Bird) e chiama :swim() solo se l'uccello sa nuotare.

Riceverai due input:

  1. Il nome dell'uccello (una stringa)
  2. Se l'uccello sa nuotare: yes o no

Se l'uccello sa nuotare, l'output dovrebbe essere:

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

Se l'uccello non sa nuotare, l'output dovrebbe essere:

{name} is eating
{name} chirps!

Per esempio, se gli input sono Duck e yes, l'output dovrebbe essere:

Duck is eating
Duck chirps!
Duck is swimming

Se gli input sono Sparrow e no, l'output dovrebbe essere:

Sparrow is eating
Sparrow chirps!

Questa sfida mostra la distinzione fondamentale: Bird è un Animal (ereditarietà), mentre nuotare è una capacità opzionale (mixin). Il mixin viene applicato alla classe, ma la logica principale decide se usarlo in base alle capacità del singolo uccello!

Provalo tu

-- main.lua: Punto de entrada: crea un pájaro y demuestra sus habilidades

-- Función auxiliar para aplicar un mixin a una clase
local function applyMixin(class, mixin)
    -- TODO: Copia todos los métodos de mixin a class
    
end

-- Aplica el mixin Swimmable a Bird antes de cargar Bird
-- Nota: Puede que necesites gestionar esto en Bird.lua o aquí

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

-- Aplica el mixin a la clase Bird
applyMixin(Bird, Swimmable)

-- Lee las entradas
local name = io.read()
local canSwimInput = io.read()

-- TODO: Determina si el pájaro puede nadar según la entrada ("yes" o "no")

-- TODO: Crea una instancia de Bird con el nombre y la capacidad de nadar

-- TODO: Llama a eat(), heredado de Animal

-- TODO: Llama a chirp(), el método propio de Bird

-- TODO: Llama a swim() solo si el pájaro puede nadar
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