Menu
Coddy logo textTech

Configurare l'ereditarietà

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

Finora hai creato classi in cui ogni oggetto cerca i metodi in un'unica tabella prototipo. Ma cosa succede se vuoi che una classe si basi su un'altra? È qui che entra in gioco l'ereditarietà: una classe figlia può accedere a tutto ciò che proviene da una classe genitore, aggiungendo al contempo le proprie funzionalità.

L'intuizione fondamentale è che una tabella di classe può avere a sua volta un metatable. Quando Lua non riesce a trovare qualcosa nella classe figlia, lo cerca in __index del metatable della classe figlia, che punta alla classe genitore.

-- Classe genitore
local Animal = {}
Animal.__index = Animal

function Animal:new()
    local obj = {}
    setmetatable(obj, Animal)
    return obj
end

function Animal:breathe()
    print("Breathing...")
end

Ora ecco la configurazione dell’ereditarietà. Creiamo una classe figlia e impostiamo la sua metatable in modo che guardi alla classe genitore:

-- Classe figlia
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})

Questa singola riga, setmetatable(Dog, {__index = Animal}), crea il collegamento di ereditarietà. Quando un'istanza di Dog chiama un metodo che non si trova in Dog, Lua controlla Animal.

La catena di ricerca funziona così: istanza → Dog → Animal. Ogni passaggio usa __index per trovare la tabella successiva in cui cercare. Questo permette alle classi figlie di ereditare automaticamente tutti i metodi della classe genitore senza copiarli.

challenge icon

Sfida

Facile

Costruiamo la tua prima gerarchia di ereditarietà! Creerai una semplice relazione tra una classe genitore e una classe figlia, in cui una classe Machine funge da base e una classe Robot eredita da essa.

Organizzerai il codice in tre file:

  • Machine.lua: Definisci la classe genitore usando il modello standard per le classi. Includi un costruttore :new() e un metodo :status() che stampa Machine is operational. Non dimenticare di impostare __index e di restituire la classe alla fine del file.
  • Robot.lua: Definisci la classe figlia che eredita da Machine. Richiedi il modulo Machine, configura la tabella Robot con il proprio __index e stabilisci il collegamento di ereditarietà usando setmetatable(Robot, {__index = Machine}). Includi un costruttore :new() che crea un'istanza con Robot come metatabella.
  • main.lua: Metti insieme tutto richiedendo il modulo Robot, creando un'istanza di Robot e chiamando il metodo ereditato :status().

Il concetto chiave è che la classe Robot non definisce autonomamente :status(). Eredita questo metodo da Machine attraverso la catena delle metatabelle. Quando chiami :status() su un'istanza di Robot, Lua cercherà prima in Robot; non trovandolo, seguirà il collegamento __index fino a Machine, dove troverà il metodo.

Il tuo output dovrebbe essere:

Machine is operational

Questa singola riga dimostra che l'ereditarietà funziona. Robot è riuscito ad accedere a un metodo definito solo nella sua classe genitore!

Provalo tu

-- main.lua: Metti tutto insieme

-- TODO: Importa il modulo Robot

-- TODO: Crea un'istanza di Robot usando Robot:new()

-- TODO: Chiama il metodo ereditato :status() sulla tua istanza di robot
-- Questo dovrebbe stampare "Machine is operational"
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