Menu
Coddy logo textTech

Metametoda __newindex

Część sekcji Logika i przepływ programu ścieżki Lua w Coddy. Lekcja 19 z 54.

Dowiedziałeś się, jak __index kontroluje to, co się dzieje, gdy próbujesz odczytać klucz, który nie istnieje w tabeli. Teraz poznasz jego odpowiednik: __newindex, który kontroluje to, co się dzieje, gdy próbujesz dodać lub zmodyfikować parę klucz-wartość.

Metametoda __newindex jest wywoływana za każdym razem, gdy próbujesz przypisać wartość do klucza, który obecnie nie istnieje w tabeli. Dzięki temu możesz przechwytywać i kontrolować modyfikacje, zanim nastąpią.

Oto prosty przykład, który uniemożliwia dodawanie nowych kluczy do tabeli:

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

setmetatable(readOnly, meta)

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

Gdy próbujesz ustawić readOnly.name = "Alice", Lua widzi, że w tabeli nie ma elementu name. Zamiast go dodać, Lua wywołuje funkcję __newindex z trzema argumentami: samą tabelą, ustawianym kluczem i przypisywaną wartością.

W tym przykładzie funkcja po prostu wyświetla komunikat i tak naprawdę niczego nie przechowuje.

Możesz również użyć __newindex, aby sprawdzać dane przed zezwoleniem na ich dodanie do tabeli:

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"  -- Wynik: Health must be a number!
player.health = 100     -- Dozwolone

Zwróć uwagę na użycie rawset() w drugim przykładzie. Ta funkcja omija metatabelę i bezpośrednio ustawia wartość w tablicy.

Bez tego ustawienie wartości ponownie wywołałoby __newindex, tworząc nieskończoną pętlę.

challenge icon

Wyzwanie

Łatwy
Napisz funkcję createValidatedTable, która przyjmuje key i value oraz zwraca tabelę, która akceptuje wyłącznie wartości typu string dla nowych kluczy.

Utwórz pustą tabelę i przypisz do niej metatabelę z __newindex, która sprawdza typ wartości. Jeśli ktoś spróbuje dodać wartość, która nie jest typu string, użyj rawset(), aby zamiast niej zapisać string "invalid". W przypadku wartości typu string zapisz je normalnie za pomocą rawset().

Logika:

  • Utwórz pustą tabelę
  • Utwórz metatabelę z __newindex, która otrzymuje tabelę, klucz i wartość
  • Wewnątrz __newindex sprawdź, czy wartość jest typu string, używając type(value) == "string"
  • Jeśli jest typu string, użyj rawset(t, key, value), aby ją zapisać
  • Jeśli nie jest typu string, użyj rawset(t, key, "invalid"), aby zamiast niej zapisać "invalid"
  • Przypisz metatabelę do tabeli za pomocą setmetatable()
  • Użyj rawset(), aby dodać do tabeli początkową parę klucz-wartość (z pominięciem metatabeli)
  • Zwróć tabelę

Parametry:

  • key (string): Początkowy klucz do dodania do tabeli
  • value (string): Początkowa wartość do dodania do tabeli

Zwraca: Tabelę z walidacją, która akceptuje wyłącznie wartości typu string i zawiera początkową parę klucz-wartość (table)

Spróbuj swoich sił

function createValidatedTable(key, value)
    -- Napisz kod tutaj
end
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Logika i przepływ programu

Poćwicz samodzielnie: Kompilator Lua online