Mixin semplici
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 51 di 70.
La composizione ti permette di inserire oggetti all'interno di altri oggetti. Ma cosa succede se vuoi condividere il comportamento tra classi non correlate?
Sia Player che MenuItem potrebbero aver bisogno di un metodo :describe(), ma non condividono una classe genitore. È qui che entrano in gioco i mixins.
Un mixin è semplicemente una tabella che contiene funzioni. Puoi "mescolare" queste funzioni in una classe copiandole al suo interno:
local Printable = {}
function Printable:describe()
print("Object: " .. tostring(self))
end
function Printable:log(message)
print("[LOG] " .. message)
endPer applicare questo mixin a una classe, copi ogni funzione dalla tabella del mixin nella tabella della classe:
local function applyMixin(class, mixin)
for key, value in pairs(mixin) do
class[key] = value
end
end
local Player = {}
Player.__index = Player
applyMixin(Player, Printable) -- Ora Player ha :describe() e :log()Dopo aver applicato il mixin, qualsiasi istanza di Player può chiamare quei metodi come se fossero definiti direttamente nella classe:
local p = setmetatable({}, Player)
p:log("Player created") -- [LOG] Player createdA differenza dell’ereditarietà, i mixin non creano una relazione genitore-figlio. Stai semplicemente copiando funzioni da una tabella all’altra.
Questo rende i mixin perfetti per condividere comportamenti utili, come la registrazione dei log, la serializzazione o i metodi di descrizione, tra classi che altrimenti non avrebbero nulla in comune.
Sfida
FacileCreiamo un sistema di tag usando i mixin! Creerai un mixin Taggable che può essere applicato a qualsiasi classe, dando agli oggetti la possibilità di gestire una raccolta di tag, utile per categorizzare elementi, post o qualsiasi entità che abbia bisogno di etichette.
Organizzerai il codice in tre file:
Taggable.lua: crea una tabella mixin contenente due metodi::addTag(tag): aggiunge un tag aself.tags(presuppone che la tabella esista):listTags(): stampa tutti i tag nel formatoTags: tag1, tag2, tag3(oTags: nonese è vuota)
Article.lua: crea una classe Article con un costruttore:new(title)che memorizza il titolo e inizializza una tabellatagsvuota. Applica il mixin Taggable per fornire alle istanze di Article la capacità di gestire i tag. Includi un metodo:getTitle()che restituisce il titolo dell'articolo.main.lua: scrivi qui la funzione helperapplyMixin(la userai in Article.lua tramite require). Poi leggi gli input per il titolo di un articolo e due tag. Crea un Article, aggiungi entrambi i tag, stampa il titolo ed elenca tutti i tag.
Riceverai tre input:
- Il titolo dell'articolo (una stringa)
- Il primo tag da aggiungere (una stringa)
- Il secondo tag da aggiungere (una stringa)
L'output dovrà mostrare il titolo dell'articolo seguito dai suoi tag:
Title: {title}
Tags: {tag1}, {tag2}Per esempio, se gli input sono Lua Basics, programming e tutorial, l'output dovrà essere:
Title: Lua Basics
Tags: programming, tutorialRicorda: i metodi del mixin funzionano perché le istanze di Article hanno una tabella tags su cui i metodi del mixin possono operare. Il mixin non crea questa tabella. È il costruttore di Article a farlo. Il mixin fornisce solo il comportamento condiviso!
Provalo tu
-- File principale del sistema di etichettatura
local Taggable = require('Taggable')
local Article = require('Article')
-- TODO: Implementare la funzione applyMixin
-- Questa funzione deve copiare tutti i metodi da una tabella mixin a una tabella di destinazione
function applyMixin(target, mixin)
-- TODO: Scorrere mixin e copiare ogni metodo in target
end
-- Leggere gli input
local title = io.read()
local tag1 = io.read()
local tag2 = io.read()
-- TODO: Creare un Article con il titolo fornito
-- TODO: Aggiungere entrambe le etichette all'articolo
-- TODO: Stampare il titolo nel formato: Title: {title}
-- TODO: Elencare tutte le etichette usando il metodo listTags
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
1Il concetto di «self»
Tabelle con funzioni«self» esplicitoLa sintassi dei due puntiPunto o due puntiRiepilogo - Spostare il punto4Progetto: Banca digitale
Configurazione del progettoMetodo di deposito2Schema del prototipo di classe
Il concetto di prototipoCollegare con __indexIl costruttore :new()Inizializzare gli attributiIstanze indipendentiRiepilogo - Fabbrica di auto5Sovraccarico degli operatori nella OOP
Sommare oggettiSottrarre oggettiConcatenare oggettiConfrontare oggetti (<, >)Ripasso - Calcoli con il portafoglio8Incapsulamento
Convenzioni di denominazioneClosure per la privacyAccesso tramite closureTabelle di sola letturaLogica di convalidaRiepilogo - Cassaforte sicura11Modelli di progettazione (base)
Funzioni factoryTabella singletonPattern IteratorObserver (listener)Riepilogo - Factory per logger3Stato e comportamento degli oggetti
Variabili di istanzaMetodi getterMetodi setterProprietà calcolateFormattazione delle stringheControlli di uguaglianzaRiepilogo - Voto dello studente6Fondamenti dell'ereditarietà
Configurare l'ereditarietàEreditare i metodiEstendere il costruttoreAggiungere metodi alla classe figliaCondiviso vs specificoRiepilogo - Gerarchia delle forme9Composizione e mixin
Relazione Has-ADelegaMixin sempliciApplicare più mixinMixin vs ereditarietàRiepilogo - Assemblaggio di robotEsercitati da solo: Compilatore Lua online