Lua Academy · Oppitunti

Luokat metataulukoilla

Simuloikaa luokkia taulukoilla ja käyttäkää __index-kenttää metodien hakuun.

Oppitunti 1/412 vaihetta

Luokat metataulukoilla on ilmainen Lua Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Lua Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Luokkataulumalli

Luokka on Luassa yksinkertaisesti taulukko, joka tallentaa metodit. Instanssit ovat taulukoita, joiden metataulun __index osoittaa luokkataulukkoon. Näin kaikki metodit ovat instanssien käytettävissä hakuketjun kautta.

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 osoittaa luokkaan

Asettamalla ClassName.__index = ClassName ilmoitetaan, että "puuttuvia avaimia haetaan luokkataulukosta". Kun instanssimetodia kutsutaan, Lua ei löydä sitä instanssista, tarkistaa metataulun (__index), löytää luokan ja hakee metodin sieltä.

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)

Rakentajamalli

new()-funktio on rakentaja: se luo taulukon, jossa on instanssin tiedot, ja palauttaa sen metatauluun käärittynä niin, että metataulu osoittaa luokkaan. Tämä on Luan vakiotapa luoda olioita.

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

Metodin ja funktion syntaksi

obj:method() on syntaktinen lyhennys muodolle obj.method(obj). Määritelkää metodit kaksoispistesyntaksilla (function Cls:method()), jotta saatte implisiittisen self-parametrin. Kutsukaa metodia kaksoispisteellä, jotta instanssi välitetään sille. Pisteen ja kaksoispisteen sekoittaminen aiheuttaa vaikeasti havaittavia virheitä.

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

Luokkatasoiset ja instanssitasoiset kentät

Luokkataulukon kentät ovat kaikkien instanssien jakamia (luokkamuuttujia). Instanssitaulukon kentät ovat instanssikohtaisia. Instanssi voi peittää luokan kentän luomalla oman samannimisen kentän.

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 luokille

Lisätkää luokkataulukkoon __tostring, jotta tulosteen esitysmuoto olisi luettava. Koska instanssin metataulu on luokka ja luokalla on __tostring, kaikki instanssit käyttävät sitä automaattisesti.

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)

Instanssin tyypin tarkistaminen

Tarkistakaa, onko olio luokan instanssi, vertaamalla sen metataulua luokkataulukkoon. Tämä vastaa Luan instanceof-toimintoa.

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

Yksityiset metodit

Yksityiset metodit ovat moduulitiedoston paikallisia funktioita. Niitä ei voi kutsua moduulin ulkopuolelta, mutta moduulin julkiset metodit voivat käyttää niitä upvalue-arvoina.

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

Luokkien vertailu

Ylikuormittakaa __eq ja __lt mukautettua yhtäsuuruus- ja järjestysvertailua varten. Lua kutsuu __eq-metamethodia taulukoille vain, kun molemmilla operandeilla on sama metataulu.

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

Useita luokkia

Kukin luokka on itsenäinen taulukko, jolla on oma metataulunsa. Eri luokkien oliolla on eri metataulut. Tämä muodostaa Lualla toteutetun moniluokkaisen olio-ohjelmointijärjestelmän perustan.

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

Pikatarkistus

Miksi asetamme ClassName.__index = ClassName?

Kertaus: luokat metataulujen avulla

Yhteenveto:

  • Luokka = taulukko + __index = self
  • Rakentaja: function Cls.new(...) return setmetatable({}, Cls) end
  • Metodit: määritellään luokkataulukossa ja kutsutaan kaksoispistesyntaksilla
  • Luokan ja instanssin kentät: luokan kentät jaetaan, instanssin kentät ovat oliokohtaisia
  • Tyypin tarkistus: getmetatable(obj) == Cls
Aloita maksutta

Opi Lua tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
40
Oppitunnit
159

Usein kysytyt kysymykset

Onko oppitunti ”Luokat metataulukoilla” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Lua Academy-oppimispolun 3 oppituntia, myös oppitunnin “Luokat metataulukoilla”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Lua Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Luokat metataulukoilla”?

Simuloikaa luokkia taulukoilla ja käyttäkää __index-kenttää metodien hakuun. Harjoittelet Lua Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Lua Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Lua Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Luokat metataulukoilla”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Lua Academy-oppitunnilla?

Kyllä. Jokainen Lua Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Luokat metataulukoilla
  2. Rakentajat ja new()
  3. Instanssimetodit ja self
  4. Kapselointi sulkeumilla
← Takaisin: Lua Academy