Lua Academy · Pelajaran

Kelas melalui Metajadual

Simulasikan kelas menggunakan jadual dan __index untuk mencari kaedah.

Pelajaran 1 daripada 412 langkah

Kelas melalui Metajadual ialah pelajaran Lua Academy percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Lua Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Pola Jadual Kelas

Dalam Lua, "kelas" hanyalah jadual yang menyimpan kaedah. Contoh ialah jadual yang metatabelnya mempunyai __index yang menunjuk kepada jadual kelas. Ini menjadikan semua kaedah boleh dicapai pada contoh melalui rantaian carian.

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 Menunjuk kepada Kelas

Menetapkan ClassName.__index = ClassName bermaksud "cari kunci yang tiada dalam jadual kelas." Apabila kaedah contoh dipanggil, Lua tidak menemuinya dalam contoh, lalu menyemak metatabel (__index), menemui kelas dan mencari kaedah tersebut di situ.

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)

Pola Pembina

Fungsi new() ialah pembina: ia mencipta jadual dengan data contoh dan mengembalikannya dalam metatabel yang menunjuk kepada kelas. Ini ialah cara standard untuk mencipta objek dalam 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()))

Sintaks Kaedah berbanding Fungsi

obj:method() ialah bentuk ringkas bagi obj.method(obj). Takrifkan kaedah dengan sintaks titik bertindih (function Cls:method()) untuk mendapatkan self secara tersirat. Panggil dengan titik bertindih untuk menghantar contoh tersebut. Mencampurkan titik dan titik bertindih menyebabkan pepijat yang sukar dikesan.

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

Medan Peringkat Kelas berbanding Peringkat Contoh

Medan pada jadual kelas dikongsi oleh semua contoh (pemboleh ubah kelas). Medan pada jadual contoh adalah khusus bagi setiap contoh. Sesuatu contoh boleh menindih medan kelas dengan mencipta medannya sendiri menggunakan nama yang sama.

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 untuk Kelas

Tambah __tostring pada jadual kelas untuk menghasilkan output cetakan yang mudah dibaca. Oleh sebab metatabel contoh ialah kelas, dan kelas mempunyai __tostring, semua contoh akan menggunakannya secara automatik.

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)

Menyemak Jenis Contoh

Semak sama ada objek ialah contoh sesuatu kelas dengan membandingkan metatabelnya dengan jadual kelas. Ini ialah setara instanceof dalam Lua.

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

Kaedah Persendirian

Kaedah persendirian ialah fungsi setempat dalam fail modul. Kaedah ini tidak boleh dipanggil dari luar, tetapi boleh dicapai dari dalam kaedah awam modul sebagai nilai upvalue.

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

Perbandingan Kelas

Lebihkan beban __eq dan __lt untuk kesamaan dan susunan tersuai. Lua hanya memanggil __eq bagi jadual apabila kedua-dua operan berkongsi metatabel yang sama.

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

Beberapa Kelas

Setiap kelas ialah jadual bebas dengan metatabelnya sendiri. Objek daripada kelas yang berbeza mempunyai metatabel yang berbeza. Ini ialah asas bagi sistem OOP berbilang kelas dalam 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

Semakan Pantas

Mengapakah kita menetapkan ClassName.__index = ClassName?

Imbas Kembali: Kelas melalui Metatabel

Ringkasan:

  • Kelas = jadual + __index = self
  • Pembina: function Cls.new(...) return setmetatable({}, Cls) end
  • Kaedah: ditakrifkan pada jadual kelas, dipanggil dengan sintaks titik bertindih
  • Medan kelas berbanding contoh: medan kelas dikongsi, medan contoh adalah khusus bagi setiap objek
  • Semakan jenis: getmetatable(obj) == Cls
Percuma untuk bermula

Pelajari Lua dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
40
Pelajaran
159

Soalan Lazim

Adakah pelajaran “Kelas melalui Metajadual” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Lua Academy, termasuk “Kelas melalui Metajadual”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Lua Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Kelas melalui Metajadual”?

Simulasikan kelas menggunakan jadual dan __index untuk mencari kaedah. Anda berlatih Lua Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Lua Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Lua Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Kelas melalui Metajadual” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Lua Academy ini?

Ya. Setiap pelajaran Lua Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Kelas melalui Metajadual
  2. Pembina dan new()
  3. Kaedah Tika dan self
  4. Pengkapsulan dengan Closure
← Kembali ke Lua Academy