Lua - Metatables
Eine Metatabelle ist eine Tabelle, mit deren Hilfe das Verhalten einer Tabelle, an die sie angehängt ist, mithilfe eines Schlüsselsatzes und zugehöriger Metamethoden geändert werden kann. Diese Metamethoden sind leistungsstarke Lua-Funktionen, die Funktionen wie - ermöglichen
Ändern / Hinzufügen von Funktionen zu Operatoren in Tabellen.
Nach Metatabellen suchen, wenn der Schlüssel in der Tabelle nicht verfügbar ist, mit __index in Metatabelle.
Es gibt zwei wichtige Methoden, die beim Umgang mit Metatables verwendet werden:
setmetatable(table,metatable) - Mit dieser Methode wird die Metatabelle für eine Tabelle festgelegt.
getmetatable(table) - Diese Methode wird verwendet, um die Metatierbarkeit einer Tabelle zu ermitteln.
Schauen wir uns zunächst an, wie eine Tabelle als Metatable einer anderen festgelegt wird. Es ist unten gezeigt.
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
Der obige Code kann wie unten gezeigt in einer einzelnen Zeile dargestellt werden.
mytable = setmetatable({},{})
_Index
Ein einfaches Beispiel für eine Metatabelle zum Nachschlagen der Metatabelle, wenn sie nicht in der Tabelle verfügbar ist, ist unten dargestellt.
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return mytable[key]
end
end
})
print(mytable.key1,mytable.key2)
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
value1 metatablevalue
Lassen Sie uns in Schritten erklären, was im obigen Beispiel passiert ist.
Die Tabelle hier ist {key1 = "value1"}.
Metatable ist für mytable festgelegt, das eine Funktion für __index enthält, die wir als Metamethode aufrufen.
Die Metamethode sucht auf einfache Weise nach einem Index "key2". Wenn er gefunden wird, gibt er "metatablevalue" zurück, andernfalls den Wert von mytable für den entsprechenden Index.
Wir können eine vereinfachte Version des obigen Programms haben, wie unten gezeigt.
mytable = setmetatable({key1 = "value1"},
{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
Wenn wir __newindex zu metatable hinzufügen und Schlüssel in der Tabelle nicht verfügbar sind, wird das Verhalten neuer Schlüssel durch Metamethoden definiert. Ein einfaches Beispiel, in dem der Index von metatable festgelegt wird, wenn der Index in der Haupttabelle nicht verfügbar ist, ist unten angegeben.
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
Wenn Sie das obige Programm ausführen, erhalten Sie die folgende Ausgabe.
value1
nil new value 2
new value 1 nil
Sie können im obigen Programm sehen, dass ein Schlüssel, der in der Haupttabelle vorhanden ist, nur aktualisiert wird. Wenn ein Schlüssel in der Wartungsdatei nicht verfügbar ist, fügt er diesen Schlüssel der Metatabelle hinzu.
Ein weiteres Beispiel, das dieselbe Tabelle mithilfe der Rawset-Funktion aktualisiert, ist unten dargestellt.
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\""..value.."\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
new value "4"
rawset legt den Wert fest, ohne __newindex von metatable zu verwenden. Ebenso gibt es ein Rawget, das ohne Verwendung von __index einen Wert erhält.
Hinzufügen des Bedienerverhaltens zu Tabellen
Ein einfaches Beispiel zum Kombinieren von zwei Tabellen mit dem Operator + ist unten dargestellt.
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table.maxn(newtable) do
table.insert(mytable, table.maxn(mytable)+1,newtable[i])
end
return mytable
end
})
secondtable = {4,5,6}
mytable = mytable + secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
1 1
2 2
3 3
4 4
5 5
6 6
Der __add-Schlüssel ist in der Metatabelle enthalten, um das Verhalten von Operator + hinzuzufügen. Die Tabelle der Schlüssel und des entsprechenden Operators ist unten dargestellt.
Sr.Nr. | Modus & Beschreibung |
---|---|
1 | __add Ändert das Verhalten des Operators '+'. |
2 | __sub Ändert das Verhalten des Operators '-'. |
3 | __mul Ändert das Verhalten des Operators '*'. |
4 | __div Ändert das Verhalten des Operators '/'. |
5 | __mod Ändert das Verhalten des Operators '%'. |
6 | __unm Ändert das Verhalten des Operators '-'. |
7 | __concat Ändert das Verhalten des Operators '..'. |
8 | __eq Ändert das Verhalten des Operators '=='. |
9 | __lt Ändert das Verhalten des Operators '<'. |
10 | __le Ändert das Verhalten des Operators '<='. |
__Anruf
Das Hinzufügen des Verhaltens des Methodenaufrufs erfolgt mit der Anweisung __call. Ein einfaches Beispiel, das die Summe der Werte in der Haupttabelle mit der übergebenen Tabelle zurückgibt.
mytable = setmetatable({10}, {
__call = function(mytable, newtable)
sum = 0
for i = 1, table.maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table.maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {10,20,30}
print(mytable(newtable))
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
70
__tostring
Um das Verhalten der print-Anweisung zu ändern, können wir die Metamethode __tostring verwenden. Ein einfaches Beispiel ist unten gezeigt.
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "The sum of values in the table is " .. sum
end
})
print(mytable)
Wenn wir das obige Programm ausführen, erhalten wir die folgende Ausgabe.
The sum of values in the table is 60
Wenn Sie die Funktionen der Metatabelle vollständig kennen, können Sie wirklich viele Vorgänge ausführen, die ohne Verwendung sehr komplex wären. Versuchen Sie also, mehr an der Verwendung von Metatabellen mit verschiedenen Optionen in Metatabellen zu arbeiten, wie in den Beispielen erläutert, und erstellen Sie auch Ihre eigenen Beispiele.