Klasser via metatabeller
Simulér klasser ved hjælp af tabeller og __index til opslag af metoder.
Klasser via metatabeller er en gratis Lua Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Lua Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Lua Academy-kurset indeholder 4 lektioner i alt.
Mønsteret med klassetabeller
I Lua er en »klasse« blot en tabel, der gemmer metoder. Instanser er tabeller, hvis metatabels __index peger på klassetabellen. Det gør alle metoder tilgængelige på instanser via opslag i kæden.
local Animal = {}
Animal.__index = Animal
function Animal.new(name, sound)
return setmetatable({name=name, sound=sound}, Animal)
end
function Animal:speak()
print(self.name .. " says " .. self.sound)
end
local dog = Animal.new("Rex","Woof")
dog:speak() -- Rex says Woof__index peger på klassen
Hvis du indstiller ClassName.__index = ClassName, betyder det »slå manglende nøgler op i klassetabellen«. Når en instansmetode kaldes, finder Lua den ikke i instansen, kontrollerer metatabellen (__index), finder klassen og slår metoden op dér.
local Point = {}
Point.__index = Point
Point.type = "2D Point"
function Point.new(x,y)
return setmetatable({x=x,y=y}, Point)
end
function Point:magnitude()
return math.sqrt(self.x^2 + self.y^2)
end
local p = Point.new(3,4)
print(p:magnitude()) -- 5.0
print(p.type) -- 2D Point (from class)Konstruktørmønster
Funktionen new() er konstruktøren: Den opretter en tabel med instansdata og returnerer den pakket ind i en metatabel, der peger på klassen. Dette er standardmåden at oprette objekter på i Lua.
local Circle = {}
Circle.__index = Circle
function Circle.new(cx, cy, radius)
assert(radius > 0, "radius must be positive")
return setmetatable({cx=cx, cy=cy, r=radius}, Circle)
end
function Circle:area()
return math.pi * self.r^2
end
function Circle:perimeter()
return 2 * math.pi * self.r
end
local c = Circle.new(0, 0, 5)
print(string.format("Area: %.2f", c:area()))Metode- kontra funktionssyntaks
obj:method() er syntaktisk sukker for obj.method(obj). Definér metoder med kolon-syntaks (function Cls:method()) for at få et implicit self. Kald dem med kolon for at overføre instansen. Hvis du blander punktum og kolon, opstår der subtile fejl.
local Dog = {}
Dog.__index = Dog
-- Define with colon: self is implicit
function Dog:bark(times)
for i = 1, (times or 1) do
print(self.name .. ": Woof!")
end
end
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local d = Dog.new("Buddy")
d:bark(2) -- Buddy: Woof! (x2)
-- Dog.bark(d,1) -- same thing, explicit selfFelter på klasse- og instansniveau
Felter i klassetabellen deles af alle instanser (klassevariabler). Felter i instanstabellen er specifikke for hver instans. En instans kan skjule et klassefelt ved at oprette sit eget felt med samme navn.
local Entity = {}
Entity.__index = Entity
Entity.count = 0 -- class-level counter
function Entity.new(name)
Entity.count = Entity.count + 1
return setmetatable({name=name, id=Entity.count}, Entity)
end
local a = Entity.new("alpha")
local b = Entity.new("beta")
local c = Entity.new("gamma")
print(Entity.count) -- 3
print(a.id, b.id, c.id) -- 1 2 3tostring til klasser
Føj __tostring til klassetabellen for at få læsbare udskrifter. Da instansens metatabel er klassen, og klassen har __tostring, bruger alle instanser det automatisk.
local Vec2 = {}
Vec2.__index = Vec2
Vec2.__tostring = function(v)
return string.format("Vec2(%g, %g)", v.x, v.y)
end
function Vec2.new(x,y)
return setmetatable({x=x,y=y}, Vec2)
end
function Vec2.__add(a, b)
return Vec2.new(a.x+b.x, a.y+b.y)
end
local v1 = Vec2.new(1,2)
local v2 = Vec2.new(3,4)
print(v1+v2) -- Vec2(4, 6)Kontrol af instanstype
Kontrollér, om et objekt er en instans af en klasse, ved at sammenligne dets metatabel med klassetabellen. Dette er Lua's pendant til instanceof.
local Dog = {}
Dog.__index = Dog
function Dog.new(name)
return setmetatable({name=name}, Dog)
end
local function isDog(obj)
return getmetatable(obj) == Dog
end
local d = Dog.new("Rex")
local t = {}
print(isDog(d)) -- true
print(isDog(t)) -- falsePrivate metoder
Private metoder er lokale funktioner i modulfilen. De kan ikke kaldes udefra, men er tilgængelige i modulets offentlige metoder som upvalues.
local Account = {}
Account.__index = Account
-- Private helper
local function validate(amount)
return type(amount)=="number" and amount > 0
end
function Account.new(balance)
return setmetatable({balance=balance or 0}, Account)
end
function Account:deposit(amount)
assert(validate(amount), "invalid amount")
self.balance = self.balance + amount
end
function Account:getBalance() return self.balance endSammenligning af klasser
Overbelast __eq og __lt for brugerdefineret lighed og sortering. Lua kalder kun __eq for tabeller, når begge operander deler den samme metatabel.
local Temp = {}
Temp.__index = Temp
Temp.__eq = function(a,b) return a.celsius == b.celsius end
Temp.__lt = function(a,b) return a.celsius < b.celsius end
Temp.__tostring = function(t)
return t.celsius.."°C"
end
function Temp.new(c)
return setmetatable({celsius=c}, Temp)
end
local t1 = Temp.new(100)
local t2 = Temp.new(0)
print(t1 == Temp.new(100)) -- true
print(t2 < t1) -- trueFlere klasser
Hver klasse er en uafhængig tabel med sin egen metatabel. Objekter fra forskellige klasser har forskellige metatabeller. Dette er grundlaget for et objektorienteret system med flere klasser i Lua.
local Cat = {}
Cat.__index = Cat
function Cat.new(name) return setmetatable({name=name,lives=9},Cat) end
function Cat:loseLife() self.lives=self.lives-1; return self.lives end
local Dog2 = {}
Dog2.__index = Dog2
function Dog2.new(name) return setmetatable({name=name,tricks={}},Dog2) end
function Dog2:learn(t) self.tricks[#self.tricks+1]=t end
local c = Cat.new("Whiskers")
local d = Dog2.new("Buddy")
d:learn("sit"); d:learn("stay")
print(c:loseLife(), #d.tricks) -- 8 2Hurtigt tjek
Hvorfor indstiller vi ClassName.__index = ClassName?
Opsummering: Klasser via metatabeller
Opsummering:
- Klasse = tabel +
__index = self - Konstruktør:
function Cls.new(...) return setmetatable({}, Cls) end - Metoder: defineres i klassetabellen og kaldes med kolon-syntaks
- Klasse- kontra instansfelter: klassefelter deles, instansfelter er specifikke for hvert objekt
- Typekontrol:
getmetatable(obj) == Cls
Lær Lua med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 40
- Lektioner
- 159
Ofte stillede spørgsmål
Er lektionen “Klasser via metatabeller” gratis?
Ja — alle 3 lektioner i læringssporet Lua Academy, inklusive “Klasser via metatabeller”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Lua Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Klasser via metatabeller”?
Simulér klasser ved hjælp af tabeller og __index til opslag af metoder. Du øver dig i Lua Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Lua Academy?
Der kræves ingen tidligere erfaring. Lua Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Klasser via metatabeller”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Lua Academy-lektion?
Ja. Alle Lua Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Klasser via metatabeller
- Konstruktører og new()
- Instansmetoder og self
- Indkapsling med closures