เมทาตาราง

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

เมทาตารางทำให้ตารางสามารถทรงพลังมากขึ้นกว่าเดิม มันถูกแนบกับข้อมูลและมีค่าเรียกว่าเมทาเมธอด เมทาเมธอดจะถูกเรียกเมื่อมีการดำเนินการใดๆ ที่ใช้กับข้อมูลที่แนบอยู่

จัดการเมทาตาราง

ฟังก์ชันหลักสองฟังก์ชันสำหรับการเพิ่มและค้นหาเมทาตารางของตารางคือ setmetatable() และ getmetatable().


local x = {}
local metaTable = {} -- เมทาตารางก็คือตารางเช่นกัน!
setmetatable(x, metaTable) -- ให้ x มีเมทาตารางเรียกว่า metaTable!
print(getmetatable(x)) --> table: [hexadecimal memory address]

ฟังก์ชัน setmetatable() ยังส่งกลับตารางที่คุณกำลังตั้งค่าเมทาตารางด้วย ดังนั้นสคริปต์สองชุดนี้ทำสิ่งเดียวกัน:


local x = {}
setmetatable(x, {})

local x = setmetatable({}, {})

เมทาเมธอด

เมทาเมธอดคือฟังก์ชันที่ถูกเก็บอยู่ในเมทาตาราง พวกมันสามารถใช้สำหรับการเรียกตาราง การบวกตาราง หรือแม้กระทั่งการหารตารางได้เช่นกัน นี่คือรายการของเมทาเมธอดที่มีให้:

วิธีการคำอธิบาย
__index(table, index)ถูกเรียกเมื่อ table[index] ถูกเข้าถึง หาก table[index] เป็น nil สามารถตั้งค่าเป็นตารางได้ โดยในกรณีนี้ ตารางนั้นจะถูกเข้าถึง.
__newindex(table, index, value)ถูกเรียกเมื่อมีการตั้งค่า table[index] (table[index] = value) หาก table[index] เป็น nil สามารถตั้งค่าเป็นตารางได้ โดยในกรณีนี้ ตารางนั้นจะถูกเข้าถึง.
__call(table, ...)ถูกเรียกเมื่อมีการเรียกตารางเหมือนฟังก์ชัน ... คืออาร์กิวเมนต์ที่ถูกส่งมา.
__concat(table, value)ถูกเรียกเมื่อใช้ตัวดำเนินการเชื่อมโยง .. บนตาราง.
__unm(table)ถูกเรียกเมื่อใช้ตัวดำเนินการ unary บนตาราง.
__add(table, value)ตัวดำเนินการบวก +.
__sub(table, value)ตัวดำเนินการลบ .
__mul(table, value)ตัวดำเนินการคูณ *.
__div(table, value)ตัวดำเนินการหาร /.
__idiv(table, value)ตัวดำเนินการฟลอร์หาร //.
__mod(table, value)ตัวดำเนินการ modulo %.
__pow(table, value)ตัวดำเนินการยกกำลัง ^.
__tostring(table)ถูกเรียกเมื่อมีการเรียก tostring บนตาราง.
__metatableหากมี จะล็อคเมทาตาราง จนกว่า getmetatable() จะส่งกลับสิ่งนี้แทนที่จะเป็นเมทาตารางและ setmetatable() จะเกิดข้อผิดพลาด ค่าไม่ใช่ฟังก์ชัน.
__eq(table, value)ตัวดำเนินการเท่ากับ ==¹
__lt(table, value)ตัวดำเนินการน้อยกว่า <¹
__le(table, value)ตัวดำเนินการน้อยกว่าหรือเท่ากับ <=¹
__modeใช้ในตารางอ่อนแอ ประกาศว่าคีย์และ/หรือค่าของตารางอ่อนแอ หมายเหตุว่าการอ้างอิงไปยังอินสแตนซ์ Roblox จะไม่เป็นอ่อนแอ ตารางที่ถือการอ้างอิงดังกล่าวจะไม่ถูกเก็บขยะ.
__len(table)ถูกเรียกเมื่อใช้ตัวดำเนินการ # บนวัตถุ.
__iter(table)ใช้เพื่อแสดงถึงตัววนรอบที่กำหนดเองเมื่อใช้การวนรอบทั่วไป.

ควรสังเกตว่าเมื่อเขียนฟังก์ชันสำหรับเมทาเมธอดเชิงคณิตศาสตร์หรือเชิงสัมพันธ์ พารามิเตอร์ฟังก์ชันทั้งสองสามารถสลับกันได้ระหว่างตารางที่เรียกเมทาเมธอดและค่าตัวอื่น ตัวอย่างเช่น เมื่อต้องการทำการดำเนินการเวกเตอร์กับสเกลาร์ การหารไม่ใช่การกระทำที่สลับกันได้นั้น ดังนั้นหากคุณกำลังเขียนเมทาเมธอดสำหรับคลาส vector2 ของคุณ คุณควรระมัดระวังในการคำนึงถึงทั้งสองสถานการณ์


local vector2 = {__type = "vector2"}
local mt = {__index = vector2}
function mt.__div(a, b)
if type(a) == "number" then
-- a คือสเกลาร์, b คือเวกเตอร์
local scalar, vector = a, b
return vector2.new(scalar / vector.x, scalar / vector.y)
elseif type(b) == "number" then
-- a คือเวกเตอร์, b คือสเกลาร์
local vector, scalar = a, b
return vector2.new(vector.x / scalar, vector.y / scalar)
elseif (a.__type and a.__type == "vector2" and b.__type and b.__type == "vector2") then
-- a และ b เป็นเวกเตอร์ทั้งคู่
return vector2.new(a.x / b.x, a.y / b.y)
end
end
function mt.__tostring(t)
return t.x .. ", " .. t.y
end
function vector2.new(x, y)
local self = setmetatable({}, mt)
self.x = x or 0
self.y = y or 0
return self
end
local a = vector2.new(10, 5)
local b = vector2.new(-3, 4)
print(a / b) -- -3.3333333333333, 1.25
print(b / a) -- -0.3, 0.8
print(2 / a) -- 0.2, 0.4
print(a / 2) -- 5, 2.5

การใช้งาน

มีวิธีการใช้เมทาตารางมากมาย เช่น เมทาเมธอด __unm เพื่อทำให้ตารางเป็นลบ:


local metatable = {
__unm = function(t) -- __unm ใช้สำหรับตัวดำเนินการ unary -
local negated = {}
for key, value in t do
negated[key] = -value -- ทำให้ค่าทั้งหมดในตารางนี้เป็นลบ
end
return negated -- ส่งคืนตาราง
end
}
local table1 = setmetatable({10, 11, 12}, metatable)
print(table.concat(-table1, "; ")) --> -10; -11; -12

นี่คือตัวอย่างที่น่าสนใจในการประกาศโดยใช้ __index:


local metatable = {
__index = {x = 1}
}
local t = setmetatable({}, metatable)
print(t.x) --> 1

__index ถูกเรียกเมื่อ x ถูกเข้าถึงในตารางและไม่พบ Luau จะค้นหาผ่านตาราง __index เพื่อหาค่า x และเมื่อพบจะส่งคืนค่านั้น

ตอนนี้คุณสามารถทำเช่นนี้ได้ง่ายด้วยฟังก์ชันง่าย ๆ แต่ยังมีอีกมากมายที่มาจากที่นั่น ลองดูตัวอย่างนี้:


local t = {10, 20, 30}
print(t(5))

ทั่วไปแล้วคุณไม่สามารถเรียกตารางได้ แต่ด้วยเมทาตารางคุณสามารถ:


local metatable = {
__call = function(t, param)
local sum = {}
for i, value in ipairs(t) do
sum[i] = value + param -- เพิ่มอาร์กิวเมนต์ (5) เข้ากับค่า แล้ววางมันในตารางใหม่ (t).
end
return unpack(sum) -- ส่งคืนค่าตารางทีละตัว
end
}
local t = setmetatable({10, 20, 30}, metatable)
print(t(5)) --> 15 25 35

คุณยังสามารถทำสิ่งอื่น ๆ ได้มากมาย เช่นการเพิ่มตาราง:


local table1 = {10, 11, 12}
local table2 = {13, 14, 15}
for k, v in table1 + table2 do
print(k, v)
end

จะมีข้อผิดพลาดบอกว่าคุณกำลังพยายามทำการคำนวณบนตาราง แต่จะทำงานเมื่อพยายามใช้เมทาตาราง:


local metatable = {
__add = function(t1, t2)
local sum = {}
for key, value in t1 do
sum[key] = value
end
for key, value in t2 do
if sum[key] then
sum[key] += value
else
sum[key] = value
end
end
return sum
end
}
local table1 = setmetatable({10, 11, 12}, metatable)
local table2 = setmetatable({13, 14, 15}, metatable)
for k, v in table1 + table2 do
print(k, v)
end

เมื่อทำงานกับเมทาตาราง คุณอาจพบปัญหาบางอย่าง หากคุณต้องการใช้เมทาเมธอด __index เพื่อสร้างค่ารใหม่ในตาราง แต่เมทาตารางของตารางนั้นยังมีเมทาเมธอด __newindex คุณจะต้องใช้ฟังก์ชันในตัวของ Luau rawset() เพื่อตั้งค่าโดยไม่เรียกใช้เมทาเมธอดใด ๆ ดูโค้ดด้านล่างเป็นตัวอย่างสิ่งที่เกิดขึ้นหากคุณไม่ใช้ฟังก์ชันเหล่านี้


local t = setmetatable({}, {
__index = function(self, i)
self[i] = i * 10
return self[i]
end,
__newindex = function(self, i, v)
-- อย่าตั้งค่าให้กับตารางด้วยวิธีปกติ
end
})
print(t[1]) -- ทำให้เกิด stack overflow

Stack overflow จะเกิดขึ้นเมื่อคุณพยายามเรียกฟังก์ชันจากตัวเองมากเกินไป ในฟังก์ชัน __index ข้างต้น self[i] ถูกตั้งค่าเป็นค่า ดังนั้นเมื่อมันถึงบรรทัดถัดไป self[i] ควรจะมีอยู่และจะไม่เรียกใช้เมทาเมธอด __index ปัญหาคือ __newindex ไม่อนุญาตให้คุณตั้งค่า ค่า มันหยุดไม่ให้ค่าถูกเพิ่มลงในตารางด้วยวิธีมาตรฐาน t[i] = v เพื่อที่จะผ่านมันให้ใช้ฟังก์ชัน rawset():


local t = setmetatable({}, {
__index = function(self, i)
rawset(self, i, i * 10)
return self[i]
end,
__newindex = function(self, i, v)
-- อย่าตั้งค่าให้กับตารางด้วยวิธีปกติ
end
})
print(t[1]) --> 10

ใช้ชนิดข้อมูลเซต

เซต คือการรวบรวมของรายการที่ไม่มีลำดับและไม่มีองค์ประกอบซ้ำ รายการใด ๆ มี หรือ ไม่มี อยู่ภายในเซต โดยใช้เมทาตารางคุณสามารถสร้างและจัดการเซตภายในสคริปต์ Luau

วิธีพื้นฐาน

โค้ดด้านล่างรวมถึงฟังก์ชันพื้นฐานของเซต ทำให้คุณสามารถสร้างเซตใหม่ เพิ่มและลบรายการ ตรวจสอบว่าเซตมีรายการอยู่หรือไม่ และแสดงเนื้อหาของเซต


local Set = {}
Set.__index = Set
-- ฟังก์ชันเพื่อสร้างเซตจากรายการของรายการที่เลือกได้
function Set.new(items)
local newSet = {}
for key, value in items or {} do
newSet[value] = true
end
return setmetatable(newSet, Set)
end
-- ฟังก์ชันเพื่อเพิ่มรายการในเซต
function Set:add(item)
self[item] = true
end
-- ฟังก์ชันเพื่อเอาออกจากเซต
function Set:remove(item)
self[item] = nil
end
-- ฟังก์ชันเพื่อตรวจสอบว่าเซตมีรายการอยู่หรือไม่
function Set:contains(item)
return self[item] == true
end
-- ฟังก์ชันเพื่อแสดงเซตเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคสำหรับการดีบัก
function Set:output()
local elems = {}
for key, value in self do
table.insert(elems, tostring(key))
end
print(table.concat(elems, ", "))
end

สร้างเซต

สามารถสร้างเซตใหม่โดยการเรียก Set.new() พร้อมกับอาร์เรย์ของรายการที่จะเพิ่มได้


local fruits = Set.new({"Apple", "Lemon", "Orange", "Cherry", "Lime", "Peach"})

โปรดจำไว้ว่าตามคำนิยาม เซตไม่มีแนวคิดเรื่องลำดับ

เพิ่มรายการ

สามารถเพิ่มรายการในเซตที่มีอยู่ได้โดยใช้วิธี Set:add()


local fruits = Set.new({"Apple", "Lemon", "Orange", "Cherry", "Lime", "Peach"})
fruits:add("Mango")

ลบรายการ

ในการลบรายการจากเซต ให้เรียก Set:remove() พร้อมกับชื่อรายการ


local fruits = Set.new({"Apple", "Lemon", "Orange", "Cherry", "Lime", "Peach"})
fruits:remove("Orange")

ตรวจสอบรายการ

ในการตรวจสอบว่าเซตมีรายการเฉพาะอยู่หรือไม่ ให้ใช้ Set:contains()


local fruits = Set.new({"Apple", "Lemon", "Orange", "Cherry", "Lime", "Peach"})
local result1 = fruits:contains("Cherry")
print(result1) -- true
local result2 = fruits:contains("Watermelon")
print(result2) -- false

วิธีเพิ่มเติม

การดำเนินการที่มีประโยชน์อื่น ๆ สามารถนำมาปรับใช้กับเซต ทำให้คุณสามารถเปรียบเทียบรายการระหว่างเซต รวมเซต หรือหักลบเซตหนึ่งจากอีกเซตหนึ่ง

การตัดกัน

เมื่อพิจารณาเซตเป็นแผนภาพ Venn คุณสามารถรับ การตัดกัน ของสองเซตได้ดังนี้ หมายถึงรายการที่ปรากฏใน ทั้งสอง เซต


local function getIntersection(set1, set2)
local result = Set.new()
for key, value in set1 do
if set2:contains(key) then
result:add(key)
end
end
return result
end
local freshFruits = Set.new({"Mango", "Lemon", "Orange", "Cherry", "Lime", "Peach"})
local frozenFruits = Set.new({"Mango", "Peach", "Pineapple"})
local commonFruits = getIntersection(freshFruits, frozenFruits)
commonFruits:output() -- Mango, Peach

การรวม

คุณสามารถรับ การรวม ของสองเซตด้วยฟังก์ชันดังนี้ หมายถึงการรวบรวมรายการในเซตทั้งสองโดยไม่มีรายการซ้ำ โดยฟังก์ชันนี้ใช้เมทาตาราง __add เพื่อให้สามารถใช้วิธีการเพิ่มอย่างรวดเร็ว set1 + set2.


function Set:__add(otherSet)
local result = Set.new()
for entry in self do
result[entry] = true
end
for entry in otherSet do
result[entry] = true
end
return result
end
local sweetFruits = Set.new({"Apple", "Mango", "Cherry", "Peach"})
local sourFruits = Set.new({"Lemon", "Lime"})
local allFruits = sweetFruits + sourFruits
allFruits:output() -- Peach, Lime, Apple, Cherry, Lemon, Mango

การหักลบ

คุณสามารถลบรายการทั้งหมดในเซตหนึ่งจากรายการในอีกเซตหนึ่งโดยใช้ฟังก์ชันดังต่อไปนี้ เช่นเดียวกับฟังก์ชันข้างต้นฟังก์ชันนี้ใช้เมทาตาราง __sub เพื่อให้สามารถใช้วิธีการหักลบอย่างรวดเร็ว set1 - set2.


function Set:__sub(otherSet)
local result = Set.new()
for entry in self do
result[entry] = true
end
for entry in otherSet do
result[entry] = nil
end
return result
end
local allFruits = Set.new({"Apple", "Lemon", "Mango", "Cherry", "Lime", "Peach"})
local sourFruits = Set.new({"Lemon", "Lime"})
local sweetFruits = allFruits - sourFruits
sweetFruits:output() -- Mango, Apple, Cherry, Peach
©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ