__newindex Metametodu
Coddy'nin Lua Journey'sinin Logic & Flow bölümünün bir parçası — ders 19 / 54.
Bir tabloda mevcut olmayan bir anahtarı okumaya çalıştığınızda __index'in ne olacağını nasıl kontrol ettiğini öğrendiniz. Şimdi onun karşılığı olan __newindex'i keşfedeceksiniz; bu, bir anahtar-değer çifti eklemeye veya değiştirmeye çalıştığınızda ne olacağını kontrol eder.
__newindex metametodu, tabloda halihazırda bulunmayan bir anahtara değer atamaya çalıştığınızda tetiklenir. Bu, değişiklikler gerçekleşmeden önce onları yakalama ve kontrol etme gücü verir.
Bir tabloya yeni anahtarlar eklenmesini engelleyen basit bir örnek:
local readOnly = {}
local meta = {
__newindex = function(table, key, value)
print("Cannot add key: " .. key)
end
}
setmetatable(readOnly, meta)
readOnly.name = "Alice" -- Çıktı: Cannot add key: name
print(readOnly.name) -- Çıktı: nilreadOnly.name = "Alice" atamasını yapmaya çalıştığınızda, Lua name anahtarının tabloda mevcut olmadığını görür. Onu eklemek yerine Lua, __newindex fonksiyonunu üç argümanla çağırır: tablonun kendisi, ayarlanan anahtar ve atanan değer.
Bu örnekte, fonksiyon sadece bir mesaj yazdırır ve aslında hiçbir şey saklamaz.
Verileri tablonuza kabul etmeden önce doğrulamak için __newindex metodunu da kullanabilirsiniz:
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" -- Çıktı: Health must be a number!
player.health = 100 -- İzin verildiİkinci örnekte rawset() kullanımına dikkat edin. Bu fonksiyon metatabloyu atlar ve değeri doğrudan tabloya atar.
Bu olmadan, değeri ayarlamak __newindex metametodunu tekrar tetikleyerek sonsuz bir döngü oluşturur.
Görev
Kolaykey ve value parametrelerini alan ve yeni anahtarlar için yalnızca dize değerlerini kabul eden bir tablo döndüren bir createValidatedTable fonksiyonu yazın.
Boş bir tablo oluşturun ve değer türünü doğrulayan __newindex içeren bir metatablo ekleyin. Eğer birisi dize olmayan bir değer eklemeye çalışırsa, bunun yerine "invalid" dizesini saklamak için rawset() kullanın. Dize değerleri için, bunları rawset() kullanarak normal şekilde saklayın.
Mantık:
- Boş bir tablo oluşturun
- Tabloyu, anahtarı ve değeri alan
__newindexiçeren bir metatablo oluşturun __newindexiçinde,type(value) == "string"kullanarak değerin bir dize olup olmadığını kontrol edin- Eğer bir dizeyse, saklamak için
rawset(t, key, value)kullanın - Eğer bir dize değilse, bunun yerine
"invalid"saklamak içinrawset(t, key, "invalid")kullanın setmetatable()kullanarak metatabloyu tabloya ekleyin- Başlangıç anahtar-değer çiftini tabloya eklemek için (metatabloyu atlayarak)
rawset()kullanın - Tabloyu döndürün
Parametreler:
key(string): Tabloya eklenecek başlangıç anahtarıvalue(string): Tabloya eklenecek başlangıç değeri
Döndürür: Başlangıç anahtar-değer çiftini içeren, yalnızca dize değerlerini kabul eden doğrulamalı bir tablo (table)
Kopya kağıdı
__newindex metametodu, bir tabloda mevcut olmayan bir anahtara değer atamaya çalıştığınızda tetiklenir ve değişiklikleri yakalayıp kontrol etmenize olanak tanır.
Yeni anahtarların eklenmesini engelleyen temel örnek:
local readOnly = {}
local meta = {
__newindex = function(table, key, value)
print("Cannot add key: " .. key)
end
}
setmetatable(readOnly, meta)
readOnly.name = "Alice" -- Çıktı: Cannot add key: name
print(readOnly.name) -- Çıktı: nil__newindex fonksiyonu üç argüman alır: tablonun kendisi, ayarlanan anahtar ve atanan değer.
__newindex ile veri doğrulama:
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" -- Çıktı: Health must be a number!
player.health = 100 -- İzin verildiMetatabloyu atlamak ve değerleri doğrudan tabloya atamak için rawset(t, key, value) kullanın. Bu, __newindex içinde değer atarken sonsuz döngü oluşmasını engeller.
Kendin dene
function createValidatedTable(key, value)
-- Kodunuzu buraya yazın
end
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Logic & Flow bölümündeki tüm dersler
1İleri Düzey Tablo Yineleme
pairs() ile Yinelemeipairs() ile Yinelemepairs() vs. ipairs()Özet - Karakter Sayfası4Metatable'lara Giriş
Metatable Nedir?setmetatable & getmetatable__index Metametodu__newindex Metametodu__tostring MetametoduAritmetik Metametotlar Bölüm 1Aritmetik Metametotlar Bölüm 2Özet - Salt Okunur Tablo2Daha Fazla Tablo Kütüphanesi Fonksiyonu
table.concat()Tablo Oluşturma ve unpack()table.sort()Fonksiyonlar ile Özel SıralamaÖzet - Yüksek Skor Tablosu