0Pricing
Lua Academy · Lektion

Arithmetische Metamethoden

Überladen Sie +, -, *, / und andere Operatoren mit Metamethoden

Arithmetische Metamethoden ist eine kostenlose Lua Academy-Lektion auf CoddyKit. Dies ist Lektion 3 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.

Namen von Metamethoden

Lua definiert Metamethoden für alle arithmetischen Operatoren. Wenn Lua eine arithmetische Operation mit einer Tabelle sieht, sucht es in der Metatabelle der Tabelle nach der entsprechenden Metamethode. Wenn beide Operanden Tabellen sind, prüft Lua zuerst die Metatabelle des linken Operanden.

-- Operator -> Metamethod
-- a + b    -> __add
-- a - b    -> __sub
-- a * b    -> __mul
-- a / b    -> __div
-- a % b    -> __mod
-- a ^ b    -> __pow
-- a // b   -> __idiv
-- -a       -> __unm (unary minus)
-- #a       -> __len
print("Metamethods defined for all Lua operators")

__add für Vektoraddition

Definieren Sie __add für eine Vektortabelle, um + zu unterstützen. Die Metamethode erhält zwei Operanden und gibt einen neuen Wert zurück. Beide Operanden können Tabellen sein, oder einer kann eine Zahl sein – Ihre Metamethode sollte beide Fälle behandeln.

local Vec = {}
Vec.__index = Vec

Vec.__add = function(a, b)
  return setmetatable({x=a.x+b.x, y=a.y+b.y}, Vec)
end

Vec.__tostring = function(v)
  return string.format("Vec(%g,%g)", v.x, v.y)
end

function Vec.new(x,y) return setmetatable({x=x,y=y},Vec) end

local v1 = Vec.new(1,2)
local v2 = Vec.new(3,4)
print(tostring(v1 + v2))   -- Vec(4,6)

__sub, __mul und __div

Definieren Sie __sub, __mul und __div auf ähnliche Weise. Behandeln Sie bei der Multiplikation sowohl den Fall Tabelle*Tabelle als auch Tabelle*Zahl, indem Sie die Operandentypen innerhalb der Metamethode prüfen.

local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__sub = function(a,b) return V(a.x-b.x, a.y-b.y) end
Vec.__mul = function(a,b)
  if type(a)=="number" then return V(a*b.x, a*b.y)
  elseif type(b)=="number" then return V(a.x*b, a.y*b)
  else return a.x*b.x + a.y*b.y  -- dot product
  end
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end

local v = V(3,4)
print(tostring(v * 2))    -- (6,8)
print(tostring(V(1,0) - V(0,1)))  -- (1,-1)

__unm: Unäres Minus

__unm ist die Metamethode für das unäre Minuszeichen und wird aufgerufen, wenn Lua -obj auswertet. Sie erhält den Operanden (zur Konsistenz wird derselbe Wert zweimal übergeben) und gibt den negierten Wert zurück.

local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__unm = function(a) return V(-a.x, -a.y) end
Vec.__tostring = function(v)
  return string.format("(%g,%g)", v.x, v.y)
end

local v = V(3, -4)
print(tostring(-v))    -- (-3,4)
print(tostring(-(-v))) -- (3,-4)

__len für benutzerdefinierte Längen

__len wird aufgerufen, wenn #obj auf eine Tabelle ohne rohe ganzzahlige Sequenz angewendet wird. Definieren Sie die Metamethode, um für benutzerdefinierte Typen wie Mengen, Warteschlangen oder gewichtete Container eine aussagekräftige „Länge“ zurückzugeben.

local Bag = {}
Bag.__index = Bag
Bag.__len = function(b) return b._count end

function Bag.new()
  return setmetatable({_count=0, _items={}}, Bag)
end
function Bag:add(item, qty)
  self._items[item] = (self._items[item] or 0) + (qty or 1)
  self._count = self._count + (qty or 1)
end

local bag = Bag.new()
bag:add("apple", 3)
bag:add("banana", 2)
print(#bag)   -- 5

__mod und __pow

__mod verarbeitet den Operator %; __pow verarbeitet ^. Diese Metamethoden werden seltener verwendet, sind aber für benutzerdefinierte numerische Typen wie große Ganzzahlen, Brüche oder Objekte für modulare Arithmetik nützlich.

local Modular = {}
Modular.__index = Modular
local M = 1000000007

local function mod(n)
  return setmetatable({n = n % M}, Modular)
end

Modular.__add = function(a,b) return mod(a.n + b.n) end
Modular.__mul = function(a,b) return mod(a.n * b.n) end
Modular.__pow = function(a,b)
  local r, base, exp = mod(1), a, b
  while exp > 0 do
    if exp%2==1 then r = r*base end
    base = base*base; exp = math.floor(exp/2)
  end
  return r
end

print((mod(2) ^ 30).n)   -- 73741817 (2^30 mod 1e9+7)

__concat

__concat wird durch den Operator .. ausgelöst, wenn mindestens ein Operand diese Metamethode besitzt. Dadurch können Sie die Verkettung für benutzerdefinierte Typen definieren oder fluide DSLs erstellen.

local Builder = {}
Builder.__index = Builder
Builder.__concat = function(a, b)
  local result = {}
  for _, v in ipairs(a._parts) do result[#result+1] = v end
  if type(b) == "string" then result[#result+1] = b
  else for _, v in ipairs(b._parts) do result[#result+1] = v end end
  return setmetatable({_parts=result}, Builder)
end
Builder.build = function(b) return table.concat(b._parts) end

local function S(s) return setmetatable({_parts={s}},Builder) end
print((S("Hello") .. ", " .. S("World") .. "!"):build())

Vergleichsmetamethoden

__eq definiert == für Tabellen (wird nur aufgerufen, wenn beide Operanden dieselbe Metatabelle besitzen). __lt definiert <; __le definiert <=. Hinweis: ~= verwendet __eq; > verwendet __lt mit vertauschten Argumenten; >= verwendet __le.

local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end

Vec.__eq = function(a,b) return a.x==b.x and a.y==b.y end
Vec.__lt = function(a,b)
  return (a.x^2+a.y^2) < (b.x^2+b.y^2)  -- by magnitude
end

print(V(1,2) == V(1,2))  -- true
print(V(1,2) == V(1,3))  -- false
print(V(1,0) < V(2,0))   -- true (1 < 2)

Metamethoden verketten

Da Metamethoden Werte (meist neue Tabellen) zurückgeben, können Operationen auf natürliche Weise verkettet werden. Jeder Operator gibt ein neues Objekt zurück, und der nächste Operator verwendet dieses Ergebnis. So können Sie fluide arithmetische Ausdrücke für benutzerdefinierte Typen erstellen.

local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__add = function(a,b) return V(a.x+b.x,a.y+b.y) end
Vec.__mul = function(a,b)
  if type(b)=="number" then return V(a.x*b,a.y*b) end
  return V(a.x*b.x+a.y*b.y, 0)   -- simplified
end
Vec.__tostring=function(v) return "("..v.x..","..v.y..")" end

local result = V(1,0) + V(0,1) * 3
print(tostring(result))   -- (1,3)

Operationen mit gemischten Typen

Wenn Sie vec * 2 schreiben, ist der linke Operand die Tabelle. Wenn Sie 2 * vec schreiben, ist der linke Operand eine Zahl (ohne Metamethode), daher prüft Lua die Metatabelle des rechten Operanden auf __mul. Behandeln Sie in Ihrer Metamethode beide Reihenfolgen.

local Vec = {}
Vec.__index = Vec
local function V(x,y) return setmetatable({x=x,y=y},Vec) end
Vec.__tostring = function(v) return "("..v.x..","..v.y..")" end

Vec.__mul = function(a, b)
  if type(a) == "number" then
    return V(a*b.x, a*b.y)   -- scalar * vec
  elseif type(b) == "number" then
    return V(a.x*b, a.y*b)   -- vec * scalar
  end
  return a.x*b.x + a.y*b.y  -- dot product
end

print(tostring(V(1,2) * 3))  -- (3,6)
print(tostring(3 * V(1,2)))  -- (3,6)

Schnelltest

Welche Metamethode wird durch -myTable ausgelöst?

Zusammenfassung: Arithmetische Metamethoden

Zusammenfassung:

  • __add __sub __mul __div __mod __pow __idiv – binäre Arithmetik
  • __unm – unäres Minus; __len – #-Operator
  • __concat – Operator ..
  • __eq __lt __le – Vergleichsoperatoren
  • Behandeln Sie gemischte Typen (Zahl/Tabelle) innerhalb der Metamethoden

Häufig gestellte Fragen

Ist die Lektion „Arithmetische Metamethoden“ kostenlos?

Ja — der vollständige Text von „Arithmetische Metamethoden“ 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 „Arithmetische Metamethoden“?

Überladen Sie +, -, *, / und andere Operatoren mit 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 3 von 4.

Wie lange dauert die Lektion „Arithmetische Metamethoden“?

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