Collegare con __index
Fa parte della sezione Programmazione orientata agli oggetti del percorso Lua di Coddy. Lezione 7 di 70.
Hai una tabella prototipo con proprietà e metodi, ma come fai a far sì che un nuovo oggetto la utilizzi davvero? La risposta è nel metametodo __index.
Quando accedi a una chiave che non esiste in una tabella, Lua normalmente restituisce nil. Tuttavia, se la tabella ha una metatabella con un campo __index, Lua cercherà lì. Impostando __index in modo che punti al tuo prototipo, le chiavi mancanti vengono trovate automaticamente nel prototipo:
local Dog = {
species = "Canis familiaris",
legs = 4
}
function Dog:bark()
print("Woof!")
end
-- Crea un'istanza vuota
local myDog = {}
-- Collegala al prototipo
setmetatable(myDog, { __index = Dog })
print(myDog.species) -- Output: Canis familiaris
myDog:bark() -- Output: Woof!La tabella myDog è completamente vuota, eppure accedere a myDog.species funziona. Quando Lua non trova species in myDog, controlla __index della metatabella e lo trova in Dog.
Questa è la base della programmazione orientata agli oggetti in Lua. L'istanza può avere i propri dati univoci, mentre il comportamento condiviso risiede nel prototipo. Nella prossima lezione imparerai a racchiudere questo schema in una funzione costruttrice pulita.
Sfida
FacileOra mettiamo in pratica il metametodo __index! Creerai un prototipo e vi collegherai un'istanza, consentendo all'istanza di accedere a proprietà e metodi che non possiede direttamente.
Organizzerai il codice in due file:
Robot.lua: definisci una tabella prototipoRobotcon:- Un campo
modelimpostato su"RX-100" - Un campo
batteryLevelimpostato su100 - Un metodo
:status()che stampa lo stato attuale del robot
- Un campo
main.lua: richiedi il modulo Robot, quindi crea una tabella di istanza vuota e collegala al prototipo Robot usandosetmetatablecon__index. Questo consente alla tua istanza vuota di accedere a tutto ciò che proviene dal prototipo.
Riceverai un input: un nome da assegnare all'istanza del tuo robot.
Dopo aver collegato l'istanza al prototipo:
- Assegna il nome dell'input al campo
namedella tua istanza (che diventa unico per l'istanza) - Chiama il metodo
:status()sulla tua istanza
Il tuo metodo :status() dovrebbe stampare esattamente nel seguente formato:
[name] ([model]) - Battery: [batteryLevel]%Per esempio, se l'input è Sparky, l'output dovrebbe essere:
Sparky (RX-100) - Battery: 100%Nota che l'istanza ha il proprio name, ma accede a model e batteryLevel dal prototipo tramite il collegamento __index.
Provalo tu
-- Leggi l'input
local name = io.read()
-- Carica il modulo Robot con require
local Robot = require('Robot')
-- TODO: Crea una tabella vuota per l'istanza
-- TODO: Collega l'istanza al prototipo Robot usando setmetatable con __index
-- TODO: Assegna il nome ricevuto in input al campo name della tua istanza
-- TODO: Chiama il metodo :status() sulla tua istanza
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 formeEsercitati da solo: Compilatore Lua online