Lua Academy · leksjon

Klasser via metatabeller

Simuler klasser ved hjelp av tabeller og __index for oppslag av metoder.

Leksjon 1 av 412 trinn

Klasser via metatabeller er en gratis leksjon i Lua Academy på CoddyKit. Dette er leksjon 1 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.

Klassetabellmønster

I Lua er en «klasse» bare en tabell som lagrer metoder. Instanser er tabeller der metatabellens __index peker på klassetabellen. Dermed blir alle metodene tilgjengelige på instansene via oppslagskjeden.

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 peker på klassen

Ved å angi ClassName.__index = ClassName betyr De «slå opp manglende nøkler i klassetabellen». Når en instansmetode kalles, finner ikke Lua metoden i instansen, kontrollerer metatabellen (__index), finner klassen og slår opp metoden der.

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

Funksjonen new() er konstruktøren: Den oppretter en tabell med instansdata og returnerer den pakket inn i en metatabell som peker på klassen. Dette er standardmåten å opprette 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 funksjonssyntaks

obj:method() er syntaktisk sukker for obj.method(obj). Definer metoder med kolon-syntaks (function Cls:method()) for å få en implisitt self. Kall med kolon for å sende instansen. Hvis De blander punktum og kolon, oppstår subtile feil.

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 self

Felter på klasse- og instansnivå

Felter i klassetabellen deles av alle instanser (klassevariabler). Felter i instanstabellen er spesifikke for hver instans. En instans kan skjule et klassefelt ved å opprette sitt 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  3

tostring for klasser

Legg til __tostring i klassetabellen for lesbar utskrift. Siden instansens metatabell er klassen, og klassen har __tostring, bruker alle instanser den 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)

Kontrollere instanstype

Kontroller om et objekt er en instans av en klasse ved å sammenligne metatabellen med klassetabellen. Dette er Lua-ekvivalenten 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))  -- false

Private metoder

Private metoder er lokale funksjoner i modulfila. De kan ikke kalles utenfra, men er tilgjengelige i modulens 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 end

Klassesammenligning

Overstyr __eq og __lt for egendefinert likhet og sortering. Lua kaller bare __eq for tabeller når begge operandene deler samme metatabell.

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)              -- true

Flere klasser

Hver klasse er en uavhengig tabell med sin egen metatabell. Objekter fra forskjellige klasser har forskjellige metatabeller. Dette er grunnlaget for et OOP-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  2

Hurtigsjekk

Hvorfor angir vi ClassName.__index = ClassName?

Oppsummering: Klasser via metatabeller

Oppsummering:

  • Klasse = tabell + __index = self
  • Konstruktør: function Cls.new(...) return setmetatable({}, Cls) end
  • Metoder: defineres i klassetabellen og kalles med kolon-syntaks
  • Klasse- kontra instansfelter: Klassefelter deles, instansfelter er spesifikke for hvert objekt
  • Typekontroll: getmetatable(obj) == Cls
Gratis å komme i gang

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 «Klasser via metatabeller» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Lua Academy, inkludert «Klasser via metatabeller», 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 «Klasser via metatabeller»?

Simuler klasser ved hjelp av tabeller og __index for oppslag av metoder. 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 1 av 4.

Hvor lang tid tar leksjonen «Klasser via metatabeller»?

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

  1. Klasser via metatabeller
  2. Konstruktører og new()
  3. Instansmetoder og self
  4. Innkapsling med closures
← Tilbake til Lua Academy