Classi tramite metatabelle
Simuli le classi usando tabelle e __index per la ricerca dei metodi.
Classi tramite metatabelle è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Lua Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Lua Academy include 4 lezioni in totale.
Modello delle tabelle per le classi
In Lua, una «classe» è semplicemente una tabella che memorizza metodi. Le istanze sono tabelle la cui metatabella ha __index che punta alla tabella della classe. In questo modo, tutti i metodi sono accessibili dalle istanze tramite la catena di ricerca.
local Animal = {}
Animal.__index = Animal
function Animal.new(name, sound)
return setmetatable({name=name, sound=sound}, Animal)
end
function Animal:speak()
print(self.name .. " says " .. self.sound)
end
local dog = Animal.new("Rex","Woof")
dog:speak() -- Rex says Woof__index punta alla classe
Impostare ClassName.__index = ClassName significa «cercare le chiavi mancanti nella tabella della classe». Quando viene chiamato un metodo di istanza, Lua non lo trova nell'istanza, controlla la metatabella (__index), trova la classe e cerca lì il metodo.
local Point = {}
Point.__index = Point
Point.type = "2D Point"
function Point.new(x,y)
return setmetatable({x=x,y=y}, Point)
end
function Point:magnitude()
return math.sqrt(self.x^2 + self.y^2)
end
local p = Point.new(3,4)
print(p:magnitude()) -- 5.0
print(p.type) -- 2D Point (from class)Modello del costruttore
La funzione new() è il costruttore: crea una tabella con i dati dell'istanza e la restituisce racchiusa in una metatabella che punta alla classe. Questo è il modo standard per creare oggetti in Lua.
local Circle = {}
Circle.__index = Circle
function Circle.new(cx, cy, radius)
assert(radius > 0, "radius must be positive")
return setmetatable({cx=cx, cy=cy, r=radius}, Circle)
end
function Circle:area()
return math.pi * self.r^2
end
function Circle:perimeter()
return 2 * math.pi * self.r
end
local c = Circle.new(0, 0, 5)
print(string.format("Area: %.2f", c:area()))Sintassi dei metodi e delle funzioni
obj:method() è una forma abbreviata di obj.method(obj). Definisca i metodi con la sintassi dei due punti (function Cls:method()) per ottenere self implicito. Chiami il metodo con i due punti per passare l'istanza. La combinazione di punto e due punti causa bug difficili da individuare.
local Dog = {}
Dog.__index = Dog
-- Define with colon: self is implicit
function Dog:bark(times)
for i = 1, (times or 1) do
print(self.name .. ": Woof!")
end
end
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local d = Dog.new("Buddy")
d:bark(2) -- Buddy: Woof! (x2)
-- Dog.bark(d,1) -- same thing, explicit selfCampi a livello di classe e di istanza
I campi della tabella della classe sono condivisi da tutte le istanze (variabili di classe). I campi della tabella dell'istanza sono specifici di ogni istanza. Un'istanza può nascondere un campo della classe creando un proprio campo con lo stesso nome.
local Entity = {}
Entity.__index = Entity
Entity.count = 0 -- class-level counter
function Entity.new(name)
Entity.count = Entity.count + 1
return setmetatable({name=name, id=Entity.count}, Entity)
end
local a = Entity.new("alpha")
local b = Entity.new("beta")
local c = Entity.new("gamma")
print(Entity.count) -- 3
print(a.id, b.id, c.id) -- 1 2 3tostring per le classi
Aggiunga __tostring alla tabella della classe per ottenere un output di stampa leggibile. Poiché la metatabella dell'istanza è la classe e la classe contiene __tostring, tutte le istanze lo utilizzeranno automaticamente.
local Vec2 = {}
Vec2.__index = Vec2
Vec2.__tostring = function(v)
return string.format("Vec2(%g, %g)", v.x, v.y)
end
function Vec2.new(x,y)
return setmetatable({x=x,y=y}, Vec2)
end
function Vec2.__add(a, b)
return Vec2.new(a.x+b.x, a.y+b.y)
end
local v1 = Vec2.new(1,2)
local v2 = Vec2.new(3,4)
print(v1+v2) -- Vec2(4, 6)Controllo del tipo dell'istanza
Verifichi se un oggetto è un'istanza di una classe confrontando la sua metatabella con la tabella della classe. Questo è l'equivalente di instanceof in Lua.
local Dog = {}
Dog.__index = Dog
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local function isDog(obj)
return getmetatable(obj) == Dog
end
local d = Dog.new("Rex")
local t = {}
print(isDog(d)) -- true
print(isDog(t)) -- falseMetodi privati
I metodi privati sono funzioni locali nel file del modulo. Non possono essere chiamati dall'esterno, ma sono accessibili all'interno dei metodi pubblici del modulo come upvalue.
local Account = {}
Account.__index = Account
-- Private helper
local function validate(amount)
return type(amount)=="number" and amount > 0
end
function Account.new(balance)
return setmetatable({balance=balance or 0}, Account)
end
function Account:deposit(amount)
assert(validate(amount), "invalid amount")
self.balance = self.balance + amount
end
function Account:getBalance() return self.balance endConfronto tra classi
Sovrascriva __eq e __lt per definire uguaglianza e ordinamento personalizzati. Lua chiama __eq per le tabelle solo quando entrambi gli operandi condividono la stessa metatabella.
local Temp = {}
Temp.__index = Temp
Temp.__eq = function(a,b) return a.celsius == b.celsius end
Temp.__lt = function(a,b) return a.celsius < b.celsius end
Temp.__tostring = function(t)
return t.celsius.."°C"
end
function Temp.new(c)
return setmetatable({celsius=c}, Temp)
end
local t1 = Temp.new(100)
local t2 = Temp.new(0)
print(t1 == Temp.new(100)) -- true
print(t2 < t1) -- truePiù classi
Ogni classe è una tabella indipendente con la propria metatabella. Gli oggetti appartenenti a classi diverse hanno metatabelle diverse. Questa è la base di un sistema OOP multi-classe in Lua.
local Cat = {}
Cat.__index = Cat
function Cat.new(name) return setmetatable({name=name,lives=9},Cat) end
function Cat:loseLife() self.lives=self.lives-1; return self.lives end
local Dog2 = {}
Dog2.__index = Dog2
function Dog2.new(name) return setmetatable({name=name,tricks={}},Dog2) end
function Dog2:learn(t) self.tricks[#self.tricks+1]=t end
local c = Cat.new("Whiskers")
local d = Dog2.new("Buddy")
d:learn("sit"); d:learn("stay")
print(c:loseLife(), #d.tricks) -- 8 2Verifica rapida
Perché si imposta ClassName.__index = ClassName?
Riepilogo: classi tramite metatabelle
Riepilogo:
- Classe = tabella +
__index = self - Costruttore:
function Cls.new(...) return setmetatable({}, Cls) end - Metodi: definiti nella tabella della classe e chiamati con la sintassi dei due punti
- Campi della classe e dell'istanza: i campi della classe sono condivisi, quelli dell'istanza sono specifici dell'oggetto
- Controllo del tipo:
getmetatable(obj) == Cls
Domande Frequenti
La lezione «Classi tramite metatabelle» è gratuita?
Sì — il testo completo di «Classi tramite metatabelle» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Lua Academy, passa a CoddyKit PRO. Il corso Lua Academy include 4 lezioni in totale.
Cosa imparerò in «Classi tramite metatabelle»?
Simuli le classi usando tabelle e __index per la ricerca dei metodi. Eserciti Lua Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Lua Academy?
Non è richiesta alcuna esperienza precedente. Lua Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.
Quanto tempo richiede la lezione «Classi tramite metatabelle»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Lua Academy?
Sì. Ogni lezione Lua Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Classi tramite metatabelle
- Costruttori e new()
- Metodi delle istanze e self
- Incapsulamento con le closure