คลาสผ่านเมทาเทเบิล
จำลองคลาสด้วยตารางและ __index เพื่อค้นหาเมธอด
คลาสผ่านเมทาเทเบิล เป็นบทเรียน Lua Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Lua Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
รูปแบบตารางคลาส
ใน Lua “คลาส” เป็นเพียงตารางที่เก็บเมธอด อินสแตนซ์คือตารางที่เมตาเทเบิลมี __index ชี้ไปยังตารางคลาส ทำให้เข้าถึงเมธอดทั้งหมดจากอินสแตนซ์ได้ผ่านสายโซ่การค้นหา
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 ชี้ไปยังคลาส
การตั้งค่า ClassName.__index = ClassName หมายถึง “ให้ค้นหาคีย์ที่ไม่พบในตารางคลาส” เมื่อเรียกเมธอดของอินสแตนซ์ Lua จะค้นหาในอินสแตนซ์ก่อน จากนั้นตรวจสอบเมตาเทเบิล (__index) พบคลาส แล้วจึงค้นหาเมธอดในคลาสนั้น
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)รูปแบบตัวสร้าง
ฟังก์ชัน new() คือตัวสร้าง ซึ่งสร้างตารางที่มีข้อมูลของอินสแตนซ์ แล้วส่งคืนตารางนั้นโดยห่อหุ้มด้วยเมตาเทเบิลที่ชี้ไปยังคลาส นี่เป็นวิธีมาตรฐานในการสร้างออบเจ็กต์ใน 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()))ไวยากรณ์เมธอดเทียบกับฟังก์ชัน
obj:method() เป็นรูปแบบย่อของ obj.method(obj) กำหนดเมธอดด้วยไวยากรณ์โคลอน (function Cls:method()) เพื่อรับ self โดยอัตโนมัติ เรียกด้วยโคลอนเพื่อส่งอินสแตนซ์ไปด้วย การใช้จุดและโคลอนปะปนกันอาจทำให้เกิดข้อผิดพลาดที่สังเกตได้ยาก
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ฟิลด์ระดับคลาสเทียบกับระดับอินสแตนซ์
ฟิลด์ในตารางคลาสจะใช้ร่วมกันโดยทุกอินสแตนซ์ (ตัวแปรคลาส) ส่วนฟิลด์ในตารางอินสแตนซ์จะเป็นของแต่ละอินสแตนซ์ อินสแตนซ์สามารถบดบังฟิลด์ของคลาสได้ด้วยการสร้างฟิลด์ของตัวเองที่ใช้ชื่อเดียวกัน
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 สำหรับคลาส
เพิ่ม __tostring ลงในตารางคลาสเพื่อให้ผลลัพธ์การพิมพ์อ่านได้ง่าย เนื่องจากเมตาเทเบิลของอินสแตนซ์คือคลาส และคลาสมี __tostring อินสแตนซ์ทั้งหมดจึงใช้สิ่งนี้โดยอัตโนมัติ
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)การตรวจสอบประเภทอินสแตนซ์
ตรวจสอบว่าออบเจ็กต์เป็นอินสแตนซ์ของคลาสหรือไม่ โดยเปรียบเทียบเมตาเทเบิลของออบเจ็กต์กับตารางคลาส นี่คือสิ่งที่เทียบเท่ากับ instanceof ใน 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เมธอดส่วนตัว
เมธอดส่วนตัวคือฟังก์ชันภายในไฟล์โมดูล ไม่สามารถเรียกจากภายนอกได้ แต่เมธอดสาธารณะของโมดูลสามารถเข้าถึงได้ในฐานะค่าจากขอบเขตภายนอก
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การเปรียบเทียบคลาส
โอเวอร์โหลด __eq และ __lt เพื่อกำหนดการเทียบเท่าและการเรียงลำดับแบบกำหนดเอง Lua จะเรียก __eq สำหรับตารางก็ต่อเมื่อตัวถูกดำเนินการทั้งสองมีเมตาเทเบิลเดียวกัน
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หลายคลาส
แต่ละคลาสเป็นตารางอิสระที่มีเมตาเทเบิลของตัวเอง ออบเจ็กต์จากคนละคลาสจึงมีเมตาเทเบิลต่างกัน นี่คือพื้นฐานของระบบการเขียนโปรแกรมเชิงวัตถุหลายคลาสใน 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ตรวจสอบความเข้าใจอย่างรวดเร็ว
เหตุใดเราจึงตั้งค่า ClassName.__index = ClassName?
สรุป: คลาสผ่านเมตาเทเบิล
สรุป:
- คลาส = ตาราง +
__index = self - ตัวสร้าง:
function Cls.new(...) return setmetatable({}, Cls) end - เมธอด: กำหนดในตารางคลาสและเรียกด้วยไวยากรณ์โคลอน
- ฟิลด์คลาสเทียบกับฟิลด์อินสแตนซ์: ฟิลด์คลาสใช้ร่วมกัน ส่วนฟิลด์อินสแตนซ์เป็นของแต่ละออบเจ็กต์
- ตรวจสอบประเภท:
getmetatable(obj) == Cls
คำถามที่พบบ่อย
บทเรียน “คลาสผ่านเมทาเทเบิล” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คลาสผ่านเมทาเทเบิล” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Lua Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Lua Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คลาสผ่านเมทาเทเบิล”
จำลองคลาสด้วยตารางและ __index เพื่อค้นหาเมธอด คุณปฏิบัติ Lua Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Lua Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Lua Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “คลาสผ่านเมทาเทเบิล” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Lua Academy นี้ได้ไหม
ได้ บทเรียน Lua Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คลาสผ่านเมทาเทเบิล
- ตัวสร้างและ new()
- เมธอดของอินสแตนซ์และ self
- การห่อหุ้มด้วยคลอเชอร์