__index og __newindex
Fang opp lesing og skriving av felt med metamethodene __index og __newindex.
__index og __newindex er en gratis leksjon i Lua Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Lua Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Lua Academy inneholder totalt 4 leksjoner.
Oppsummering av __index
__index utløses når Lua forsøker å lese en nøkkel som ikke finnes i tabellen. Det kan være en tabell, for prototypetilslag, eller en funksjon, for dynamisk beregning. Dette er den mest brukte metametoden i Lua – den muliggjør arv, standardverdier og lat initialisering.
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 utløses
__newindex utløses når Lua forsøker å skrive en nøkkel som ikke finnes i tabellen ennå. Hvis nøkkelen allerede finnes, utføres tilordningen direkte uten å utløse __newindex.
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) -- 20Skrivebeskyttede tabeller
Bruk __newindex til å opprette skrivebeskyttede tabeller. Fang opp alle skriveoperasjoner og utløse en feil. Kombiner dette med __index for å tilby verdier uten å lagre dem i selve tabellen.
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 tableSpore endringer
Bruk __newindex til å spore alle endringer i en tabell – nyttig ved feilsøking, endringslogging eller reaktive databindinger. Lagre dataene i en skjult «backing»-tabell, og registrer endringene i en logg.
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)
endProxyobjekter
En proxy pakker inn et annet objekt for å fange opp alle lese- og skriveoperasjoner. Bruk en tom tabell som proxy, med __index og __newindex som begge peker til funksjoner. De faktiske dataene ligger i en separat tabell.
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-kjede (arv)
Ved å lenke __index-metatabeller sammen opprettes prototypisk arv. Når en nøkkel ikke finnes i objektet, undersøker Lua klassen, deretter foreldreklassen, og så videre. Hvert nivå trenger sin egen metatabell, med __index som peker til neste nivå.
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)Lat initialisering med __index
Bruk en funksjonsvariant av __index til å beregne og hurtiglagre kostbare verdier ved første tilgang. Ved første lesing beregnes verdien og lagres direkte i tabellen, slik at fremtidige __index-kall omgås.
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)__newindex for skjemavalidering
Bruk __newindex til å håndheve et skjema: Tillat bare angivelse av forhåndsdefinerte nøkler eller verdier av riktig type. Dette gir tabeller i Lua en enkel typesikkerhet.
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 kontra rawget
Inne i en __index-funksjon bør De bruke rawget til å lese fra tabellen uten å utløse __index på nytt, noe som ellers ville ført til uendelig rekursjon. Bruk alltid rawget/rawset inne i metametoder når De skal endre den faktiske tabellagringen.
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)Kombinere __index og __newindex
Det kraftigste mønsteret er å bruke en tom proxy-tabell med både __index og __newindex, støttet av en skjult datatabell. Dette gir full kontroll over lesing og skriving, og muliggjør funksjoner som endringsdeteksjon, lat lasting og tilgangskontroll.
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 -> 100Rask kontroll
Når utløses __newindex IKKE?
Oppsummering: __index og __newindex
Viktige punkter:
__index: utløses ved lesing av en manglende nøkkel; tabell eller funksjon__newindex: utløses bare ved skriving til en ny nøkkel- Bruk
rawget/rawsetinne i metametoder for å unngå rekursjon - Mønstre: skrivebeskyttede tabeller, endringssporing, lat initialisering, skjemavalidering
- Tom proxy + backing-tabell = full oppfanging av lese- og skriveoperasjoner
Lær deg Lua med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 40
- Leksjoner
- 159
Ofte stilte spørsmål
Er leksjonen «__index og __newindex» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Lua Academy, inkludert «__index og __newindex», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Lua Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «__index og __newindex»?
Fang opp lesing og skriving av felt med metamethodene __index og __newindex. Du øver på Lua Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Lua Academy?
Ingen tidligere erfaring er nødvendig. Lua Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «__index og __newindex»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Lua Academy-leksjonen?
Ja. Alle Lua Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Introduksjon til metatabeller
- __index og __newindex
- Aritmetiske metamethoder
- __tostring og __len