Menu
Coddy logo textTech

__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ı: nil

readOnly.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.

challenge icon

Görev

Kolay

key 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 __newindex içeren bir metatablo oluşturun
  • __newindex iç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çin rawset(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 verildi

Metatabloyu 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
quiz iconKendini test et

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