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: nilGdy 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 -- DozwoloneZwróć 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ę.
Wyzwanie
ŁatwyNapisz 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
__newindexsprawdź, czy wartość jest typu string, używająctype(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 tabelivalue(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
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
1Zaawansowane iterowanie po tabelach
Iterowanie za pomocą pairs()Iterowanie za pomocą ipairs()pairs() a ipairs()Powtórka — karta postaci2Więcej funkcji biblioteki table
table.concat()Tworzenie tabel i unpack()table.sort()Sortowanie niestandardowe za pomocą funkcjiPodsumowanie — tablica najlepszych wyników5Projekt: silnik tekstowej gry przygodowej
Konfiguracja projektu: pokójŁączenie pokoiPoćwicz samodzielnie: Kompilator Lua online