Costruttori e new()
Scriva funzioni costruttrici che creino e inizializzino le istanze.
Costruttori e new() è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 2 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.
Responsabilità del costruttore
Un costruttore crea e inizializza un'istanza. Riceve i valori iniziali, li convalida, assegna valori predefiniti ai campi mancanti e restituisce la nuova istanza. Un costruttore ben progettato garantisce che ogni istanza inizi in uno stato valido.
local Player = {}
Player.__index = Player
function Player.new(name, hp, mp)
assert(type(name)=="string" and name~="","need name")
return setmetatable({
name = name,
hp = hp or 100,
mp = mp or 50,
alive = true,
items = {},
}, Player)
end
local p = Player.new("Hero")
print(p.name, p.hp, p.mp) -- Hero 100 50Costruttore fluente
Un costruttore fluente restituisce self dai metodi setter, consentendo di concatenare i metodi durante la costruzione. In Lua, questo è un builder pattern.
local Config = {}
Config.__index = Config
function Config.new()
return setmetatable({_data={}}, Config)
end
function Config:set(k,v) self._data[k]=v; return self end
function Config:build() return self._data end
local cfg = Config.new()
:set("host","localhost")
:set("port",8080)
:set("debug",true)
:build()
print(cfg.host, cfg.port)Costruttore di copia
Un costruttore di copia crea una nuova istanza con gli stessi valori di una già esistente. Importante: utilizzi una copia superficiale o profonda a seconda che le tabelle annidate debbano essere condivise o indipendenti.
local function deepCopy(orig)
if type(orig)~="table" then return orig end
local copy = {}
for k,v in pairs(orig) do copy[deepCopy(k)]=deepCopy(v) end
return setmetatable(copy, getmetatable(orig))
end
local Item = {}
Item.__index = Item
function Item.new(name, stats)
return setmetatable({name=name, stats=stats or {}}, Item)
end
function Item:clone()
return deepCopy(self)
end
local sword = Item.new("Sword",{damage=50})
local clone = sword:clone()
clone.stats.damage = 30
print(sword.stats.damage) -- 50 (unchanged)Costruttore con convalida
Convalidi sempre gli input del costruttore. Generi errori descrittivi per gli input non validi al livello 2 (responsabilità del chiamante). Questo consente di individuare rapidamente i bug e produce messaggi di errore utili.
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle.new(w, h)
assert(type(w)=="number" and w>0,"width must be positive number")
assert(type(h)=="number" and h>0,"height must be positive number")
return setmetatable({width=w, height=h}, Rectangle)
end
function Rectangle:area() return self.width * self.height end
function Rectangle:perimeter() return 2*(self.width+self.height) end
local r = Rectangle.new(5, 3)
print(r:area(), r:perimeter()) -- 15 16Pattern dei valori predefiniti
Utilizzi una tabella dei valori predefiniti per gestire in modo ordinato i parametri opzionali del costruttore. In questo modo evita lunghe catene di x = x or default e rende i valori predefiniti espliciti e facili da modificare.
local Sprite = {}
Sprite.__index = Sprite
local DEFAULTS = {x=0,y=0,rotation=0,scale=1,visible=true,alpha=1}
function Sprite.new(image, opts)
local cfg = opts or {}
local self = {image=image}
for k,v in pairs(DEFAULTS) do
self[k] = cfg[k] ~= nil and cfg[k] or v
end
return setmetatable(self, Sprite)
end
local s = Sprite.new("hero.png",{x=100,y=200})
print(s.x,s.y,s.scale) -- 100 200 1Metodi factory statici
Una classe può avere diversi metodi factory per scenari di creazione differenti. È più ordinato che sovraccaricare un singolo costruttore con molti parametri opzionali.
local Color = {}
Color.__index = Color
function Color.fromRGB(r,g,b)
return setmetatable({r=r,g=g,b=b}, Color)
end
function Color.fromHex(hex)
hex = hex:gsub("#","")
return setmetatable({
r=tonumber(hex:sub(1,2),16),
g=tonumber(hex:sub(3,4),16),
b=tonumber(hex:sub(5,6),16),
}, Color)
end
function Color:toHex()
return string.format("#%02X%02X%02X",self.r,self.g,self.b)
end
local red = Color.fromHex("#FF0000")
print(red:toHex()) -- #FF0000Registro dei costruttori
Utilizzi un registro per tenere traccia di tutte le istanze. Questo consente operazioni globali come "distruggi tutto" o l'iterazione su tutti gli oggetti di un tipo.
local Enemy = {}
Enemy.__index = Enemy
Enemy._all = {}
function Enemy.new(name, hp)
local self = setmetatable({name=name, hp=hp}, Enemy)
Enemy._all[#Enemy._all+1] = self
return self
end
function Enemy.destroyAll()
for _, e in ipairs(Enemy._all) do
print("Destroying:", e.name)
end
Enemy._all = {}
end
Enemy.new("Goblin",30)
Enemy.new("Orc",80)
print("Count:", #Enemy._all) -- 2
Enemy.destroyAll()Inizializzazione lazy
Alcuni campi sono costosi da calcolare. Utilizzi __index con una funzione per calcolarli e memorizzarli nella cache al primo accesso.
local BigData = {}
BigData.__index = function(t, k)
if k == "processed" then
print("Computing processed...")
local result = {}
for i,v in ipairs(rawget(t,"raw")) do result[i]=v*2 end
rawset(t,"processed",result)
return result
end
end
function BigData.new(raw)
return setmetatable({raw=raw}, BigData)
end
local d = BigData.new({1,2,3,4,5})
print(d.processed[3]) -- Computing... 6
print(d.processed[3]) -- 6 (cached, no recompute)Prototipo da un'istanza
Cloni un'istanza per crearne un'altra con gli stessi valori di base. Il clone ottiene la stessa metatabella (la stessa classe) e una copia dei dati dell'istanza. È utile per gli oggetti "modello".
local Unit = {}
Unit.__index = Unit
function Unit.new(t)
return setmetatable({name=t.name,hp=t.hp,atk=t.atk}, Unit)
end
function Unit:clone()
return Unit.new({name=self.name,hp=self.hp,atk=self.atk})
end
function Unit:__tostring()
return self.name.."(HP:"..self.hp..",ATK:"..self.atk..")"
end
local template = Unit.new({name="Soldier",hp=100,atk=10})
local u1 = template:clone(); u1.name="Alpha"
local u2 = template:clone(); u2.name="Beta"
print(tostring(u1),tostring(u2))Sicurezza dagli errori nel costruttore
Se la costruzione fallisce a metà (ad esempio durante l'allocazione di una risorsa), si assicuri che non sfuggano oggetti parzialmente creati. Utilizzi pcall per intercettare gli errori di costruzione e, se necessario, liberare le risorse.
local FileHandle = {}
FileHandle.__index = FileHandle
function FileHandle.new(path, mode)
local f, err = io.open(path, mode or "r")
if not f then
return nil, "cannot open " .. path .. ": " .. err
end
return setmetatable({_f=f, path=path}, FileHandle)
end
function FileHandle:read(fmt) return self._f:read(fmt) end
function FileHandle:close() self._f:close() end
local fh, err = FileHandle.new("data.txt")
if not fh then print("Error:", err)
else print(fh:read("l")); fh:close()
endVerifica rapida
Qual è il ruolo di un costruttore (new()) nella programmazione OOP in Lua?
Riepilogo: costruttori
Riepilogo:
- Il costruttore convalida, inizializza e chiama setmetatable
- Utilizzi una tabella dei valori predefiniti per gestire ordinatamente i parametri opzionali
- Utilizzi più metodi factory per scenari di creazione differenti
- Utilizzi un costruttore di clonazione per gli oggetti modello
- Utilizzi l'inizializzazione lazy tramite __index per i campi costosi da calcolare
- In caso di errore, il costruttore restituisce nil+err (allocazione di risorse)
Domande Frequenti
La lezione «Costruttori e new()» è gratuita?
Sì — il testo completo di «Costruttori e new()» è 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 «Costruttori e new()»?
Scriva funzioni costruttrici che creino e inizializzino le istanze. 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 2 di 4.
Quanto tempo richiede la lezione «Costruttori e new()»?
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