0Pricing
Lua Academy · Lezione

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 self

Campi 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  3

tostring 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))  -- false

Metodi 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 end

Confronto 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)              -- true

Più 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  2

Verifica 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

  1. Classi tramite metatabelle
  2. Costruttori e new()
  3. Metodi delle istanze e self
  4. Incapsulamento con le closure
← Torna a Lua Academy