Menu
CoddyTech

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