0Pricing
Lua Academy · Lektion

__tostring und __len

Steuern Sie die Zeichenkettendarstellung und den #-Operator über Metamethoden

__tostring und __len ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Lua Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.

__tostring-Metamethode

__tostring wird aufgerufen, wenn tostring(obj) aufgerufen wird, und auch von print() (das für jedes Argument tostring aufruft). Definieren Sie die Metamethode, um eine gut lesbare Darstellung Ihrer benutzerdefinierten Objekte bereitzustellen.

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 für Sequenzen

__len wird aufgerufen, wenn der Operator # auf eine Tabelle mit dieser Metamethode angewendet wird. In Lua 5.2+ wird __len für Tabellen immer aufgerufen; in 5.1 nur für userdata. Verwenden Sie die Metamethode, um die „Länge“ benutzerdefinierter Container zu definieren.

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

Aussagekräftiges __tostring für Debugging

Ein gutes __tostring enthält den Typnamen und wichtige Schlüssel. Bei verschachtelten Objekten rufen Sie tostring rekursiv auf. Dadurch wird das Debugging deutlich einfacher als mit der standardmäßigen Ausgabe "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 im Vergleich zum #-Operator

Bei Tabellen ohne eine __len-Metamethode sucht #t eine beliebige Grenze der Sequenz (bei der t[i] ~= nil und t[i+1] == nil gilt). Bei Lücken in der Tabelle ist das Ergebnis unvorhersehbar. Mit __len können Sie eine verbindliche, konsistente Länge definieren.

-- 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 in Fehlermeldungen

Wenn Sie Fehlerobjekte verwenden (Tabellen anstelle von Strings), werden Fehlermeldungen durch die Definition von __tostring lesbar, wenn der Fehler weitergereicht und in einen String umgewandelt wird.

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 mit Vererbung

Wenn Sie objektorientierte Programmierung auf Prototypbasis verwenden, definieren Sie __tostring in der Klassenmetatabelle. Alle Instanzen verwenden automatisch das __tostring der Klasse, da die Metatabelle der Instanz DIE Klassentabelle ist.

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)

Eine Menge mit __len und __tostring implementieren

Kombinieren Sie __len und __tostring in einem Typ, um eine vollständige, benutzerfreundliche Implementierung einer Menge zu erstellen.

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}

Numerische Objekte mit beiden Metamethoden

Erstellen Sie einen Bruchtyp mit __tostring für die Anzeige und __len als Ziffernanzahl (oder als domänenspezifische Kennzahl).

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/6

Das standardmäßige Verhalten von print überschreiben

Lua ruft für jedes durch Tabulatoren getrennte Argument von print tostring auf. Wenn __tostring definiert ist, werden Ihre Objekte in jeder print-Anweisung, Fehlermeldung oder String-Interpolation, die tostring verwendet, sinnvoll dargestellt.

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+ unterstützt ein __name-Feld in der Metatabelle, das von den standardmäßigen Fehlermeldungen zur Identifizierung des Typs verwendet wird. Es beeinflusst tostring() zwar nicht direkt, erscheint aber in Laufzeitfehlermeldungen, wenn Sie ungültige Operationen für den Typ ausführen.

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)

Schnelltest

Wann wird __tostring aufgerufen?

Zusammenfassung: __tostring und __len

Zusammenfassung:

  • __tostring: wird von tostring() und print() aufgerufen
  • __len: wird von #obj aufgerufen und liefert die verbindliche Länge für benutzerdefinierte Container
  • Definieren Sie __tostring in Klassentabellen, damit es für alle Instanzen gilt
  • Verwenden Sie __len, wenn die rohe Tabellenstruktur nicht die korrekte Länge für # liefert
  • __name (5.3+) benennt den Typ in Fehlermeldungen

Häufig gestellte Fragen

Ist die Lektion „__tostring und __len“ kostenlos?

Ja — der vollständige Text von „__tostring und __len“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Lua Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Lua Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „__tostring und __len“?

Steuern Sie die Zeichenkettendarstellung und den #-Operator über Metamethoden Du übst Lua Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Lua Academy zu starten?

Keine Vorkenntnisse erforderlich. Lua Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „__tostring und __len“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Lua Academy-Lektion Code schreiben und ausführen?

Ja. Jede Lua Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Einführung in Metatabellen
  2. __index und __newindex
  3. Arithmetische Metamethoden
  4. __tostring und __len
← Zurück zu Lua Academy