__tostring e __len
Controlli la rappresentazione come stringa e l'operatore # tramite i metametodi.
__tostring e __len è una lezione Lua Academy gratuita su CoddyKit. Questa è la lezione 4 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.
Metam metodo __tostring
__tostring viene chiamato quando si invoca tostring(obj) e anche da print(), che chiama tostring su ogni argomento. Lo definisca per fornire una rappresentazione leggibile dei propri oggetti personalizzati.
local Point = {}
Point.__index = Point
Point.__tostring = function(p)
return string.format("Point(%.2f, %.2f)", p.x, p.y)
end
function Point.new(x,y)
return setmetatable({x=x,y=y}, Point)
end
local p = Point.new(3.14, 2.72)
print(p) -- Point(3.14, 2.72)
print(tostring(p)) -- Point(3.14, 2.72)__len per le sequenze
__len viene chiamato quando l'operatore # viene applicato a una tabella con questo metametodo. In Lua 5.2 e versioni successive, __len viene sempre chiamato per le tabelle; nella versione 5.1 viene chiamato solo per gli userdata. Lo usi per definire la "lunghezza" di contenitori personalizzati.
local Queue = {}
Queue.__index = Queue
Queue.__len = function(q) return q._tail - q._head + 1 end
function Queue.new()
return setmetatable({_data={},_head=1,_tail=0}, Queue)
end
function Queue:push(v)
self._tail = self._tail + 1
self._data[self._tail] = v
end
function Queue:pop()
if self._head > self._tail then return nil end
local v = self._data[self._head]
self._head = self._head + 1
return v
end
local q = Queue.new()
q:push("a"); q:push("b"); q:push("c")
print(#q) -- 3__tostring dettagliato per il debug
Un buon __tostring include il nome del tipo e i campi principali. Per gli oggetti annidati, chiami tostring ricorsivamente. In questo modo il debug è molto più semplice rispetto all'output predefinito "table: 0x...".
local function tableToString(t, depth)
depth = depth or 0
if depth > 3 then return "{...}" end
local parts = {}
for k, v in pairs(t) do
if type(v) == "table" then
parts[#parts+1] = k.."="..tableToString(v, depth+1)
else
parts[#parts+1] = k.."="..tostring(v)
end
end
return "{"..table.concat(parts,", ").."}"
end
local obj = {name="test", data={x=1,y=2}, active=true}
print(tableToString(obj))__len e operatore # a confronto
Per le tabelle senza un metametodo __len, #t trova un qualsiasi bordo della sequenza (dove t[i] ~= nil e t[i+1] == nil). Se la tabella contiene elementi mancanti, il risultato è imprevedibile. __len consente di definire una lunghezza autorevole e coerente.
-- Table with hole: # is unpredictable
local t = {10, 20, nil, 40}
print(#t) -- could be 2 or 4, undefined!
-- Custom container with authoritative length
local SafeList = {}
SafeList.__index = SafeList
SafeList.__len = function(s) return s._size end
function SafeList.new()
return setmetatable({_data={}, _size=0}, SafeList)
end
function SafeList:add(v)
self._size = self._size + 1
self._data[self._size] = v
end
local s = SafeList.new()
s:add(1); s:add(nil); s:add(3)
print(#s) -- 3 (always correct)__tostring nei messaggi di errore
Quando usa oggetti di errore (tabelle invece di stringhe), definire __tostring rende leggibili i messaggi di errore quando l'errore si propaga e viene convertito in una stringa.
local function makeError(code, msg)
return setmetatable(
{code=code, message=msg},
{__tostring = function(e)
return string.format("Error[%d]: %s", e.code, e.message)
end}
)
end
local ok, err = pcall(function()
error(makeError(404, "resource not found"))
end)
if not ok then
-- err is the error object (table)
print(tostring(err)) -- may show table address...__tostring con l'ereditarietà
Quando usa la programmazione a oggetti basata sui prototipi, definisca __tostring sulla metatabella della classe. Tutte le istanze useranno automaticamente il __tostring della classe, perché la metatabella dell'istanza È la tabella della classe.
local Animal = {}
Animal.__index = Animal
Animal.__tostring = function(a)
return string.format("%s(%s)", a._type or "Animal", a.name or "?")
end
function Animal.new(name, atype)
return setmetatable({name=name, _type=atype}, Animal)
end
local cat = Animal.new("Whiskers", "Cat")
local dog = Animal.new("Rex", "Dog")
print(cat) -- Cat(Whiskers)
print(dog) -- Dog(Rex)Implementare un Set con __len e __tostring
Combini __len e __tostring in un unico tipo per ottenere un'implementazione completa e intuitiva di Set.
local Set = {}
Set.__index = Set
Set.__len = function(s) return s._size end
Set.__tostring = function(s)
local items = {}
for k in pairs(s._data) do items[#items+1]=tostring(k) end
table.sort(items)
return "Set{" .. table.concat(items,", ") .. "}"
end
function Set.new(...)
local obj = setmetatable({_data={},_size=0}, Set)
for _, v in ipairs({...}) do
if not obj._data[v] then obj._data[v]=true; obj._size=obj._size+1 end
end
return obj
end
local s = Set.new(3,1,4,1,5,9,2,6)
print(#s) -- 7 (duplicates removed)
print(tostring(s)) -- Set{1, 2, 3, 4, 5, 6, 9}Oggetti numerici con entrambi i metametodi
Crei un tipo frazione con __tostring per la visualizzazione e __len come conteggio delle cifre (o come metrica specifica del dominio).
local Frac = {}
Frac.__index = Frac
local function gcd(a,b) return b==0 and a or gcd(b,a%b) end
function Frac.new(n,d)
local g = gcd(math.abs(n), math.abs(d))
return setmetatable({n=n//g, d=d//g}, Frac)
end
Frac.__tostring = function(f)
if f.d==1 then return tostring(f.n) end
return f.n .. "/" .. f.d
end
Frac.__add = function(a,b)
return Frac.new(a.n*b.d + b.n*a.d, a.d*b.d)
end
local a = Frac.new(1,2)
local b = Frac.new(1,3)
print(a + b) -- 5/6Sovrascrivere il comportamento predefinito di print
Il print di Lua chiama tostring su ogni argomento, separandoli con tabulazioni. Quando __tostring è definito, gli oggetti vengono visualizzati in modo significativo in qualsiasi istruzione print, messaggio di errore o interpolazione di stringhe che usa tostring.
local Color = {}
Color.__index = Color
Color.__tostring = function(c)
return string.format("#%02X%02X%02X", c.r, c.g, c.b)
end
function Color.new(r,g,b)
return setmetatable({r=r,g=g,b=b}, Color)
end
local red = Color.new(255,0,0)
local green = Color.new(0,255,0)
local blue = Color.new(0,0,255)
print(red, green, blue)
-- #FF0000 #00FF00 #0000FF__name in Lua 5.3+
Lua 5.3 e versioni successive supportano un campo __name nella metatabella, usato dai messaggi di errore predefiniti per identificare il tipo. Sebbene non influisca direttamente su tostring(), compare nei messaggi di errore di runtime quando si eseguono operazioni non valide sul tipo.
local MyType = {}
MyType.__index = MyType
MyType.__name = "MyType" -- used in error messages
MyType.__tostring = function(t)
return "MyType(" .. tostring(t.value) .. ")"
end
local obj = setmetatable({value=42}, MyType)
print(obj) -- MyType(42)
-- Error message will say "MyType" instead of "table"
-- pcall(function() local x = obj + 1 end)Verifica rapida
Quando viene chiamato __tostring?
Riepilogo: __tostring e __len
Riepilogo:
__tostring: viene chiamato datostring()eprint()__len: viene chiamato da#obj; fornisce una lunghezza autorevole per i contenitori personalizzati- Definisca
__tostringnelle tabelle di classe per applicarlo a tutte le istanze - Usi
__lenquando la struttura grezza della tabella non fornisce il valore corretto per# __name(5.3+) assegna il nome al tipo nei messaggi di errore
Domande Frequenti
La lezione «__tostring e __len» è gratuita?
Sì — il testo completo di «__tostring e __len» è 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 «__tostring e __len»?
Controlli la rappresentazione come stringa e l'operatore # tramite i metametodi. 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 4 di 4.
Quanto tempo richiede la lezione «__tostring e __len»?
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
- Introduzione alle metatabelle
- __index e __newindex
- Metametodi aritmetici
- __tostring e __len