Lua Academy · Lektion

Konstruktører og new()

Skriv konstruktørfunktioner, der opretter og initialiserer instanser.

Lektion 2 af 412 trin

Konstruktører og new() er en gratis Lua Academy-lektion på CoddyKit. Dette er lektion 2 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.

Konstruktørens ansvar

En konstruktør opretter og initialiserer en instans. Den modtager startværdier, validerer dem, angiver standardværdier for manglende felter og returnerer den nye instans. En veldesignet konstruktør sikrer, at alle instanser starter i en gyldig tilstand.

local Player = {}
Player.__index = Player

function Player.new(name, hp, mp)
  assert(type(name)=="string" and name~="","need name")
  return setmetatable({
    name = name,
    hp   = hp or 100,
    mp   = mp or 50,
    alive = true,
    items = {},
  }, Player)
end

local p = Player.new("Hero")
print(p.name, p.hp, p.mp)  -- Hero  100  50

Flydende konstruktør

En flydende konstruktør returnerer self fra setter-metoder, så du kan kæde metoder under oprettelsen. Dette er et builder-mønster i Lua.

local Config = {}
Config.__index = Config

function Config.new()
  return setmetatable({_data={}}, Config)
end

function Config:set(k,v) self._data[k]=v; return self end
function Config:build() return self._data end

local cfg = Config.new()
  :set("host","localhost")
  :set("port",8080)
  :set("debug",true)
  :build()

print(cfg.host, cfg.port)

Kopikonstruktør

En kopikonstruktør opretter en ny instans med de samme værdier som en eksisterende instans. Vigtigt: Brug en overfladisk eller dyb kopi afhængigt af, om indlejrede tabeller skal deles eller være uafhængige.

local function deepCopy(orig)
  if type(orig)~="table" then return orig end
  local copy = {}
  for k,v in pairs(orig) do copy[deepCopy(k)]=deepCopy(v) end
  return setmetatable(copy, getmetatable(orig))
end

local Item = {}
Item.__index = Item

function Item.new(name, stats)
  return setmetatable({name=name, stats=stats or {}}, Item)
end

function Item:clone()
  return deepCopy(self)
end

local sword = Item.new("Sword",{damage=50})
local clone = sword:clone()
clone.stats.damage = 30
print(sword.stats.damage)  -- 50 (unchanged)

Konstruktør med validering

Validér altid konstruktørens input. Kast beskrivende fejl ved ugyldigt input på niveau 2 (den kaldende kode har ansvaret). Det opdager fejl tidligt og giver nyttige fejlmeddelelser.

local Rectangle = {}
Rectangle.__index = Rectangle

function Rectangle.new(w, h)
  assert(type(w)=="number" and w>0,"width must be positive number")
  assert(type(h)=="number" and h>0,"height must be positive number")
  return setmetatable({width=w, height=h}, Rectangle)
end

function Rectangle:area() return self.width * self.height end
function Rectangle:perimeter() return 2*(self.width+self.height) end

local r = Rectangle.new(5, 3)
print(r:area(), r:perimeter())  -- 15  16

Mønsteret med standardværdier

Brug en tabel med standardværdier til at håndtere valgfrie konstruktørparametre på en enkel måde. Det undgår lange kæder af x = x or default og gør standardværdierne tydelige og nemme at ændre.

local Sprite = {}
Sprite.__index = Sprite

local DEFAULTS = {x=0,y=0,rotation=0,scale=1,visible=true,alpha=1}

function Sprite.new(image, opts)
  local cfg = opts or {}
  local self = {image=image}
  for k,v in pairs(DEFAULTS) do
    self[k] = cfg[k] ~= nil and cfg[k] or v
  end
  return setmetatable(self, Sprite)
end

local s = Sprite.new("hero.png",{x=100,y=200})
print(s.x,s.y,s.scale)  -- 100 200 1

Statiske fabriksmetoder

En klasse kan have flere fabriksmetoder til forskellige oprettelsesscenarier. Det er mere overskueligt end at overbelaste en enkelt konstruktør med mange valgfrie parametre.

local Color = {}
Color.__index = Color

function Color.fromRGB(r,g,b)
  return setmetatable({r=r,g=g,b=b}, Color)
end

function Color.fromHex(hex)
  hex = hex:gsub("#","")
  return setmetatable({
    r=tonumber(hex:sub(1,2),16),
    g=tonumber(hex:sub(3,4),16),
    b=tonumber(hex:sub(5,6),16),
  }, Color)
end

function Color:toHex()
  return string.format("#%02X%02X%02X",self.r,self.g,self.b)
end

local red = Color.fromHex("#FF0000")
print(red:toHex())  -- #FF0000

Konstruktørregister

Brug et register til at holde styr på alle instanser. Det gør globale handlinger som "ødelæg alle" eller gennemløb af alle objekter af en bestemt type mulige.

local Enemy = {}
Enemy.__index = Enemy
Enemy._all = {}

function Enemy.new(name, hp)
  local self = setmetatable({name=name, hp=hp}, Enemy)
  Enemy._all[#Enemy._all+1] = self
  return self
end

function Enemy.destroyAll()
  for _, e in ipairs(Enemy._all) do
    print("Destroying:", e.name)
  end
  Enemy._all = {}
end

Enemy.new("Goblin",30)
Enemy.new("Orc",80)
print("Count:", #Enemy._all)  -- 2
Enemy.destroyAll()

Doven initialisering

Nogle felter er dyre at beregne. Brug __index sammen med en funktion til at beregne og cache dem ved første adgang.

local BigData = {}
BigData.__index = function(t, k)
  if k == "processed" then
    print("Computing processed...")
    local result = {}
    for i,v in ipairs(rawget(t,"raw")) do result[i]=v*2 end
    rawset(t,"processed",result)
    return result
  end
end

function BigData.new(raw)
  return setmetatable({raw=raw}, BigData)
end

local d = BigData.new({1,2,3,4,5})
print(d.processed[3])  -- Computing...  6
print(d.processed[3])  -- 6 (cached, no recompute)

Prototype fra instans

Klon en instans for at oprette en anden med de samme grundværdier. Klonen får den samme metatabel (den samme klasse) og en kopi af instansens data. Det er nyttigt til "skabelonobjekter".

local Unit = {}
Unit.__index = Unit

function Unit.new(t)
  return setmetatable({name=t.name,hp=t.hp,atk=t.atk}, Unit)
end

function Unit:clone()
  return Unit.new({name=self.name,hp=self.hp,atk=self.atk})
end

function Unit:__tostring()
  return self.name.."(HP:"..self.hp..",ATK:"..self.atk..")"
end

local template = Unit.new({name="Soldier",hp=100,atk=10})
local u1 = template:clone(); u1.name="Alpha"
local u2 = template:clone(); u2.name="Beta"
print(tostring(u1),tostring(u2))

Fejlsikkerhed i konstruktøren

Hvis oprettelsen mislykkes undervejs (f.eks. ved allokering af en ressource), skal du sikre, at ingen delvist oprettede objekter slipper ud. Brug pcall til at fange fejl under oprettelsen, og ryd om nødvendigt ressourcer op.

local FileHandle = {}
FileHandle.__index = FileHandle

function FileHandle.new(path, mode)
  local f, err = io.open(path, mode or "r")
  if not f then
    return nil, "cannot open " .. path .. ": " .. err
  end
  return setmetatable({_f=f, path=path}, FileHandle)
end

function FileHandle:read(fmt) return self._f:read(fmt) end
function FileHandle:close() self._f:close() end

local fh, err = FileHandle.new("data.txt")
if not fh then print("Error:", err)
else print(fh:read("l")); fh:close()
end

Hurtigt tjek

Hvilken rolle har en konstruktør (new()) i Luas OOP?

Opsummering: Konstruktører

Opsummering:

  • Konstruktøren validerer, initialiserer og kalder setmetatable
  • Brug en tabel med standardværdier til rene valgfrie parametre
  • Flere fabriksmetoder til forskellige oprettelsesscenarier
  • Kloningskonstruktør til skabelonobjekter
  • Doven initialisering via __index til dyre felter
  • Returnér nil+err fra konstruktøren ved fejl (allokering af en ressource)
Gratis at komme i gang

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 “Konstruktører og new()” gratis?

Ja — alle 3 lektioner i læringssporet Lua Academy, inklusive “Konstruktører og new()”, 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 “Konstruktører og new()”?

Skriv konstruktørfunktioner, der opretter og initialiserer instanser. 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 2 af 4.

Hvor lang tid tager lektionen “Konstruktører og new()”?

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

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