English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Lua 元表(Metatable)

In Lua-Tabellen können wir die entsprechenden Schlüssel verwenden, um Werte zu erhalten, aber wir können zwei Tabellen nicht operieren.

Daher bietet Lua Metatables an, um das Verhalten von Tabellen zu ändern, wobei jedes Verhalten einem entsprechenden Metamethoden zugeordnet ist.

Zum Beispiel können wir mit Metatables definieren, wie Lua die Addition von zwei Tabellen berechnet.+b.

Wenn Lua versucht, zwei Tabellen zu addieren, überprüft es zuerst, ob eine der beiden Tabellen einen Metatable hat, und dann überprüft es, ob es ein Feld namens "__add" gibt. Wenn es gefunden wird, wird der entsprechende Wert aufgerufen. "__add"-Felder sind sofort und deren Werte (meistens eine Funktion oder eine Tabelle) sind "Metamethoden".

Es gibt zwei sehr wichtige Funktionen, um Metatables zu verarbeiten:

  • setmetatable(table, metatable): Setze den Metatable (metatable) für die angegebene Tabelle, wenn im Metatable (metatable) der Schlüssel __metatable existiert, wird setmetatable fehlschlagen.

  • getmetatable(table): Rückgabeobjekt Metatable (metatable).

Nachfolgender Beispiel zeigt, wie man einem bestimmten Tisch einen Metatable setzt:

mytable = {}                          -- Regulärer Tisch 
mymetatable = {}                      -- Metatable
setmetatable(mytable, mymetatable)     -- Setze mymetatable als Metatable von mytable

Der obige Code kann auch in einer Zeile direkt geschrieben werden:

mytable = setmetatable({}, {})

Hier ist das Rückgabeobjekt Metatable:

getmetatable(mytable)                 -- Das gibt zurück mymetatable

__index-Metamethode

Das ist der häufigste Schlüssel im Metatable.

Wenn du eine Tabelle über einen Schlüssel abrufst und dieser Schlüssel keinen Wert hat, sucht Lua nach dem __index-Schlüssel im Metatable der Tabelle (angenommen, es gibt einen Metatable). Wenn __index eine Tabelle enthält, sucht Lua in dieser Tabelle nach dem entsprechenden Schlüssel.

Wir können den Interaktionsmodus mit dem lua-Befehl betreten und ansehen:

$ lua
Lua 5.3.0         Copyright (C) 1994-2015 Lua.org, PUC-Rio
> other = { foo = 3 } 
> t = setmetatable({}, { __index = other }) 
> t.foo
3
> t.bar
nil

Wenn __index eine Funktion enthält, ruft Lua diese Funktion auf und überträgt die Tabelle und den Schlüssel als Parameter an die Funktion.

__index-Metamethode überprüft, ob das Element in der Tabelle existiert, wenn nicht existiert, wird der Rückgabewert nil sein; wenn existiert, wird der Rückgabewert von __index zurückgegeben.

mytable = setmetatable({key1 = "Wert"1"}, {
  __index = function(mytable, key)
    if key == "key2" then
      return "metatablevalue"
    else
      return nil
    end
  end
)
print(mytable.key1,mytable.key2)

Beispiel-Ausgabeergebnis:

value1    metatablevalue

Beispielanalyse:

  • mytable-Tabelle zugewiesen {key1 = "value1"}

  • mytable hat eine Metatabelle eingerichtet, die Metamethode ist __index.

  • In der mytable-Tabelle nach key suchen1,wenn gefunden, wird das Element zurückgegeben, wenn nicht gefunden, wird fortgesetzt.

  • In der mytable-Tabelle nach key suchen2,wenn gefunden, wird metatablevalue zurückgegeben, wenn nicht gefunden, wird fortgesetzt.

  • Überprüfen Sie, ob die Metatabelle __index hat, wenn __index eine Funktion ist, wird diese Funktion aufgerufen.

  • In der Metamethode überprüfen, ob "key2" Schlüsselparameter (mytable.key2Bereits gesetzt),wenn "key2" Parameter wird "metatablevalue" zurückgegeben, andernfalls wird der Wert des mytable entsprechenden Schlüssels zurückgegeben.

Wir können den obigen Code einfach schreiben:

mytable = setmetatable({key1 = "Wert"1"}, { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)

Zusammenfassung

Die Regeln für die Suche nach einem Tabellenelement in Lua sind im Grunde wie folgt 3 Schritte:

  • 1.Suchen Sie in der Tabelle, wenn Sie das Element finden, wird es zurückgegeben, wenn nicht gefunden, wird fortgesetzt

  • 2.Überprüfen Sie, ob die Tabelle eine Metatabelle hat, wenn keine Metatabelle vorhanden ist, wird nil zurückgegeben, wenn eine Metatabelle vorhanden ist, wird fortgesetzt.

  • 3.Überprüfen Sie, ob die Metatabelle __index hat, wenn __index eine nil ist, wird nil zurückgegeben; wenn __index eine Tabelle ist, wird wiederholt 1、2、3;wenn die __index-Methode eine Funktion ist, wird der Rückgabewert dieser Funktion zurückgegeben.

Dieser Teil des Inhalts stammt von dem Autor Huanzi: https://blog.csdn.net/xocoder/article/details/9028347

__newindex-Metamethode

__newindex-Metamethode wird verwendet, um Tabellen zu aktualisieren, während __index zur Abrufung von Tabellen verwendet wird.

Wenn Sie einem fehlenden Index einer Tabelle einen Wert zuweisen, sucht der Interpreter nach der __newindex-Metamethode: Wenn diese Methode existiert, wird sie aufgerufen, ohne dass eine Zuweisung durchgeführt wird.

Nachfolgender Beispiel zeigt die Anwendung der __newindex-Metamethode:

mymetatable = {}
mytable = setmetatable({key1 = "Wert"1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "neuer Wert"2"
print(mytable.newkey, mymetatable.newkey)
mytable.key1 = "neuer Wert"1"
print(mytable.key1,mymetatable.key1)

Das Ausgaberesultat des obigen Beispiels ist:

value1
nil    neuer Wert2
neuer Wert1    nil

In diesem Beispiel wurde die Tabelle den Metamethoden __newindex zugeordnet, bei der Zuweisung neuer Indexschlüssel (mytable.newkey = "neuer Wert2wird aufgerufen, ohne eine Zuweisung durchzuführen. Und wenn ein bestehender Indexschlüssel (key1) wird eine Zuweisung durchgeführt, ohne den Metamethoden __newindex aufzurufen.

Nachfolgender Beispiel zeigt die Verwendung der Funktion rawset, um die Tabelle zu aktualisieren:

mytable = setmetatable({key1 = "Wert"1"}, {
  __newindex = function(mytable, key, value)
                rawset(mytable, key, "\""..value.."\"")
  end
)
mytable.key1 = "neue Wert"
mytable.key2 = 4
print(mytable.key1,mytable.key2)

Das Ausgaberesultat des obigen Beispiels ist:

neue Wert    "4"

Operationen hinzufügen für die Tabelle

Nachfolgender Beispiel zeigt die Zusammenführung der beiden Tabellen:

-- Berechnen Sie den größten Wert im Array, table.maxn in Lua5.2Diese Version kann nicht mehr verwendet werden
-- Definieren Sie die benutzerdefinierte Funktion table_maxn, um die Anzahl der Elemente in der Tabelle zu berechnen
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end
-- Zusammenführung der beiden Tabellen
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

Das Ausgaberesultat des obigen Beispiels ist:

1    1
2    2
3    3
4    4
5    5
6    6

__add Schlüssel enthält die Metatabelle und führt die Addition durch. Die zugehörige Liste der Operationen in der Tabelle ist wie folgt: (Hinweis:__ist zwei Unterstriche)

MusterBeschreibung
__addentspricht dem Operator ''+'
__subentspricht dem Operator ''-'
__mulentspricht dem Operator ''*'
__diventspricht dem Operator ''/'
__modentspricht dem Operator '%'.
__unmentspricht dem Operator ''-'
__concatentspricht dem Operator '..'.
__eqentspricht dem Operator '=='.
__ltentspricht dem Operator '<'.
__leentspricht dem Operator '<='.

__call Metamethode

__call Metamethode wird aufgerufen, wenn ein Wert in Lua aufgerufen wird. Nachfolgender Beispiel zeigt die Berechnung der Summe der Elemente einer Tabelle:

-- Berechnen Sie den größten Wert im Array, table.maxn in Lua5.2Diese Version kann nicht mehr verwendet werden
-- Definieren Sie die benutzerdefinierte Funktion table_maxn, um die Anzahl der Elemente in der Tabelle zu berechnen
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end
-- Definieren Sie die Metamethode __call
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))

Das Ausgaberesultat des obigen Beispiels ist:

70

__tostring Metamethode

Die __tostring-Metamethode wird verwendet, um das Ausgabeverhalten von Tabellen zu ändern. Im folgenden Beispiel haben wir die Ausgabeinhalte der Tabelle angepasst:

mytable = setmetatable({ 10, 20, 30 }, {
  __tostring = function(mytable)
    sum = 0
    for k, v in pairs(mytable) do
                sum = sum + v
        end
    return "Die Summe aller Elemente im Array beträgt" .. sum
  end
)
print(mytable)

Das Ausgaberesultat des obigen Beispiels ist:

Die Summe aller Elemente im Array beträgt 60

Von diesem Artikel können wir wissen, dass Metatables unsere Code-Funktionen sehr gut vereinfachen können. Daher ist es wichtig, die Metatables von Lua zu verstehen, um einfacher und bessere Lua-Code zu schreiben.