Menu
Coddy logo textTech

Die __newindex-Metamethode

Teil des Abschnitts Logic & Flow der Lua-Journey von Coddy — Lektion 19 von 54.

Sie haben gelernt, wie __index steuert, was passiert, wenn Sie versuchen, einen Schlüssel zu lesen, der in einer Tabelle nicht existiert. Jetzt werden Sie sein Gegenstück entdecken: __newindex, das steuert, was passiert, wenn Sie versuchen, ein Schlüssel-Wert-Paar hinzuzufügen oder zu ändern.

Die __newindex-Metamethode wird immer dann ausgelöst, wenn Sie versuchen, einem Schlüssel einen Wert zuzuweisen, der derzeit nicht in der Tabelle existiert. Dies gibt Ihnen die Möglichkeit, Änderungen abzufangen und zu steuern, bevor sie stattfinden.

Hier ist ein einfaches Beispiel, das verhindert, dass neue Schlüssel zu einer Tabelle hinzugefügt werden:

local readOnly = {}
local meta = {
    __newindex = function(table, key, value)
        print("Cannot add key: " .. key)
    end
}

setmetatable(readOnly, meta)

readOnly.name = "Alice"  -- Ausgabe: Cannot add key: name
print(readOnly.name)     -- Ausgabe: nil

Wenn Sie versuchen, readOnly.name = "Alice" zu setzen, sieht Lua, dass name in der Tabelle nicht existiert. Anstatt es hinzuzufügen, ruft Lua die __newindex-Funktion mit drei Argumenten auf: die Tabelle selbst, der zu setzende Schlüssel und der zugewiesene Wert.

In diesem Beispiel gibt die Funktion einfach eine Nachricht aus und speichert eigentlich nichts.

Du kannst auch __newindex verwenden, um Daten zu validieren, bevor sie in deine Tabelle aufgenommen werden:

local player = {}
local meta = {
    __newindex = function(t, key, value)
        if key == "health" and type(value) ~= "number" then
            print("Health must be a number!")
        else
            rawset(t, key, value)
        end
    end
}

setmetatable(player, meta)

player.health = "high"  -- Ausgabe: Health must be a number!
player.health = 100     -- Erlaubt

Beachten Sie die Verwendung von rawset() im zweiten Beispiel. Diese Funktion umgeht die Metatabelle und setzt den Wert direkt in der Tabelle.

Ohne dies würde das Setzen des Wertes __newindex erneut auslösen und so eine Endlosschleife erzeugen.

challenge icon

Aufgabe

Einfach

Schreiben Sie eine Funktion createValidatedTable, die key und value entgegennimmt und eine Tabelle zurückgibt, die nur String-Werte für neue Schlüssel akzeptiert.

Erstellen Sie eine leere Tabelle und fügen Sie eine Metatabelle mit __newindex hinzu, die den Werttyp validiert. Wenn jemand versucht, einen Nicht-String-Wert hinzuzufügen, verwenden Sie rawset(), um stattdessen den String "invalid" zu speichern. Für String-Werte speichern Sie diese normal mit rawset().

Logik:

  • Erstellen Sie eine leere Tabelle
  • Erstellen Sie eine Metatabelle mit __newindex, die die Tabelle, den Schlüssel und den Wert empfängt
  • Überprüfen Sie innerhalb von __newindex mit type(value) == "string", ob der Wert ein String ist
  • Wenn es ein String ist, verwenden Sie rawset(t, key, value), um ihn zu speichern
  • Wenn es kein String ist, verwenden Sie rawset(t, key, "invalid"), um stattdessen "invalid" zu speichern
  • Verknüpfen Sie die Metatabelle mit der Tabelle unter Verwendung von setmetatable()
  • Verwenden Sie rawset(), um das initiale Schlüssel-Wert-Paar zur Tabelle hinzuzufügen (unter Umgehung der Metatabelle)
  • Geben Sie die Tabelle zurück

Parameter:

  • key (string): Der initiale Schlüssel, der der Tabelle hinzugefügt werden soll
  • value (string): Der initiale Wert, der der Tabelle hinzugefügt werden soll

Rückgabewert: Eine Tabelle mit Validierung, die nur String-Werte akzeptiert und das initiale Schlüssel-Wert-Paar enthält (table)

Spickzettel

Die Metamethode __newindex wird ausgelöst, wenn Sie versuchen, einem Schlüssel, der in einer Tabelle nicht existiert, einen Wert zuzuweisen, was es Ihnen ermöglicht, Änderungen abzufangen und zu steuern.

Einfaches Beispiel, das neue Schlüssel verhindert:

local readOnly = {}
local meta = {
    __newindex = function(table, key, value)
        print("Cannot add key: " .. key)
    end
}

setmetatable(readOnly, meta)

readOnly.name = "Alice"  -- Ausgabe: Cannot add key: name
print(readOnly.name)     -- Ausgabe: nil

Die Funktion __newindex erhält drei Argumente: die Tabelle selbst, den Schlüssel, der gesetzt wird, und den Wert, der zugewiesen wird.

Validierung von Daten mit __newindex:

local player = {}
local meta = {
    __newindex = function(t, key, value)
        if key == "health" and type(value) ~= "number" then
            print("Health must be a number!")
        else
            rawset(t, key, value)
        end
    end
}

setmetatable(player, meta)

player.health = "high"  -- Ausgabe: Health must be a number!
player.health = 100     -- Erlaubt

Verwenden Sie rawset(t, key, value), um die Metatabelle zu umgehen und Werte direkt in der Tabelle zu setzen. Dies verhindert Endlosschleifen beim Setzen von Werten innerhalb von __newindex.

Probier es selbst

function createValidatedTable(key, value)
    -- Code hier schreiben
end
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Logic & Flow