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.