0Pricing
Lua Academy · Ders

__index ve __newindex

Alan okumalarını ve yazmalarını __index ve __newindex üst yöntemleriyle araya girerek yönetin.

__index ve __newindex, CoddyKit'te ücretsiz bir Lua Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Lua Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Lua Academy kursu toplamda 4 dersten oluşur.

__index Özeti

Lua tabloda bulunmayan bir anahtarı okumaya çalıştığında __index tetiklenir. Bu alan bir tablo (prototip araması) veya bir işlev (dinamik hesaplama) olabilir. Bu, Lua'da en çok kullanılan metamethod'dur; kalıtımı, varsayılan değerleri ve tembel başlatmayı mümkün kılar.

local defaults = {timeout=30, retries=3}
local config = setmetatable({timeout=60}, {__index=defaults})

print(config.timeout)   -- 60 (own value)
print(config.retries)   -- 3  (from defaults)
print(config.missing)   -- nil (not in either)

__newindex Tetiklendiğinde

Lua tabloda henüz bulunmayan bir anahtara yazmaya çalıştığında __newindex tetiklenir. Anahtar zaten varsa atama doğrudan yapılır ve __newindex tetiklenmez.

local proxy = setmetatable({}, {
  __newindex = function(t, k, v)
    print("New key:", k, "=", v)
    rawset(t, k, v)  -- actually store it
  end
})

proxy.x = 10    -- New key: x = 10
proxy.x = 20    -- no trigger! x already exists
print(proxy.x)  -- 20

Salt Okunur Tablolar

Salt okunur tablolar oluşturmak için __newindex kullanın. Tüm yazma işlemlerini yakalayıp bir hata oluşturun. Değerleri tablonun kendisinde saklamadan sunmak için bunu __index ile birleştirin.

local function readOnly(t)
  return setmetatable({}, {
    __index = t,
    __newindex = function(_, k, _)
      error("attempt to write to read-only table key: " .. tostring(k), 2)
    end
  })
end

local cfg = readOnly({host="localhost", port=8080})
print(cfg.host)    -- localhost
-- cfg.host = "x"  -- ERROR: attempt to write to read-only table

Değişiklikleri İzleme

Bir tablodaki tüm değişiklikleri izlemek için __newindex kullanın; bu, hata ayıklama, değişiklik günlüğü tutma veya reaktif veri bağlama için kullanışlıdır. Verileri gizli bir "destek" tablosunda saklayın ve değişiklikleri bir günlüğe kaydedin.

local log = {}
local data = {}
local tracked = setmetatable({}, {
  __index = data,
  __newindex = function(_, k, v)
    log[#log+1] = {key=k, old=data[k], new=v}
    data[k] = v
  end
})

tracked.name = "Alice"
tracked.age = 30
tracked.name = "Bob"

for _, entry in ipairs(log) do
  print(entry.key, entry.old, "->", entry.new)
end

Vekil Nesneler

Bir vekil, tüm okuma ve yazma işlemlerini yakalamak için başka bir nesneyi sarar. __index ve __newindex alanlarının her ikisini de işlevlere yönlendiren boş bir tabloyu vekil olarak kullanın. Gerçek veriler ayrı bir tabloda bulunur.

local function makeProxy(target)
  return setmetatable({}, {
    __index = function(_, k) return target[k] end,
    __newindex = function(_, k, v)
      print("Setting", k, "on target")
      target[k] = v
    end,
  })
end

local real = {x=10}
local p = makeProxy(real)
print(p.x)   -- 10 (reads from real)
p.y = 20     -- Setting y on target
print(real.y) -- 20

__index Zinciri (Kalıtım)

__index metatable'larını zincirlemek prototip kalıtımı oluşturur. Bir anahtar nesnede bulunamadığında Lua önce sınıfı, sonra üst sınıfı ve bu şekilde devamını denetler. Her düzeyin, __index alanı sonraki düzeye yönlendiren kendi metatable'ı olmalıdır.

local Base  = {type = "base",  version = 1}
local Child = setmetatable({type = "child"}, {__index = Base})
local Obj   = setmetatable({}, {__index = Child})

print(Obj.type)     -- base? No: child (Child has it)
print(Obj.version)  -- 1 (from Base)
print(Obj.type)     -- child (Child overrides Base.type)

__index ile Tembel Başlatma

İlk erişimde pahalı değerleri hesaplamak ve önbelleğe almak için işlev biçimindeki __index alanını kullanın. İlk okumada değeri hesaplayıp doğrudan tabloda saklayın (gelecekteki __index çağrılarını atlamak için).

local lazy = setmetatable({}, {
  __index = function(t, k)
    if k == "expensiveData" then
      print("Computing...")
      local result = {1,2,3,4,5}   -- simulate work
      rawset(t, k, result)
      return result
    end
  end
})

print(lazy.expensiveData)  -- Computing...  then table
print(lazy.expensiveData)  -- (no "Computing" this time)

Şema Doğrulama için __newindex

Bir şemayı zorunlu kılmak için __newindex kullanın: yalnızca önceden tanımlanmış anahtarların veya doğru türdeki değerlerin ayarlanmasına izin verin. Bu, Lua tablolarına hafif bir tür güvenliği ekler.

local schema = {name="string", age="number", active="boolean"}

local function schemaTable()
  local store = {}
  return setmetatable({}, {
    __index = store,
    __newindex = function(_, k, v)
      local expected = schema[k]
      if not expected then error("unknown key: "..k,2) end
      if type(v) ~= expected then
        error(k.." must be "..expected..", got "..type(v),2)
      end
      store[k] = v
    end
  })
end

local user = schemaTable()
user.name = "Alice"
user.age  = 30
-- user.age = "thirty"  -- ERROR

__index ve rawget Karşılaştırması

Bir __index işlevinin içinde, __index işlevini yeniden tetiklemeden tablodan okumak için rawget kullanın (aksi durumda sonsuz özyineleme oluşur). Gerçek tablo depolamasını değiştirmek için metamethod'ların içinde her zaman rawget/rawset kullanın.

local counter = setmetatable({count=0}, {
  __index = function(t, k)
    -- Use rawget to avoid recursion
    local c = rawget(t, "count")
    rawset(t, "count", c + 1)
    return rawget(t, k)
  end
})

print(counter.count)    -- 0 (direct, no __index)
print(counter.missing)  -- nil
print(counter.count)    -- 1 (incremented)

__index ve __newindex'i Birleştirme

En güçlü yaklaşım şudur: Gizli bir veri tablosuyla desteklenen ve hem __index hem de __newindex alanlarına sahip boş bir vekil tablo kullanın. Bu, okuma ve yazma işlemleri üzerinde tam denetim sağlayarak değişiklik algılama, tembel yükleme ve erişim denetimi gibi özellikleri mümkün kılar.

local function observable(init)
  local data = init or {}
  local listeners = {}
  local obj = setmetatable({}, {
    __index = data,
    __newindex = function(_, k, v)
      local old = data[k]
      data[k] = v
      for _, cb in ipairs(listeners) do cb(k,old,v) end
    end
  })
  obj._onchange = function(_, cb) listeners[#listeners+1]=cb end
  return obj
end

local obs = observable({score=0})
obs:_onchange(function(k,o,n) print(k,o,"->",n) end)
obs.score = 100  -- score  0 -> 100

Hızlı Denetim

__newindex ne zaman tetiklenmez?

Özet: __index ve __newindex

Temel noktalar:

  • __index: bulunmayan bir anahtar okunduğunda tetiklenir; tablo veya işlev olabilir
  • __newindex: yalnızca yeni bir anahtara yazıldığında tetiklenir
  • Özyinelemeyi önlemek için metamethod'ların içinde rawget/rawset kullanın
  • Yaklaşımlar: salt okunur tablolar, değişiklik izleme, tembel başlatma, şema doğrulama
  • Boş vekil + destek tablosu = okuma ve yazma işlemlerini tamamen yakalama

Sıkça Sorulan Sorular

“__index ve __newindex” dersi ücretsiz mi?

Evet — “__index ve __newindex” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Lua Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Lua Academy kursu toplamda 4 dersten oluşur.

“__index ve __newindex” dersinde ne öğreneceğim?

Alan okumalarını ve yazmalarını __index ve __newindex üst yöntemleriyle araya girerek yönetin. Lua Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Lua Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Lua Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.

“__index ve __newindex” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Lua Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Lua Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Üst Tablolara Giriş
  2. __index ve __newindex
  3. Aritmetik Üst Yöntemleri
  4. __tostring ve __len
← Lua Academy Sayfasına Dön