Lua 元表(Metatable)学习笔记
什么是元表?
在 Lua 中,每个值都可以有一个元表(metatable)。元表是一个 Lua 表,其中存储了一些元方法(metamethods)。当 Lua 需要对一个值执行特定的操作时,如果该值具有元表,则会查找元表中是否有对应操作的元方法。如果找到了对应的元方法,Lua 就会调用该元方法来完成操作。
如何设置元表?
通过 Lua 的 setmetatable 函数可以设置一个值的元表。setmetatable 函数接受两个参数:第一个参数是需要设置元表的值,第二个参数是元表。例如:
Copy Codelocal t1 = {1, 2, 3}
local mt = {}
setmetatable(t1, mt)
上述代码创建了一个名为 t1 的表,并将其元表设置为 mt。
常用的元方法
Lua 中定义了许多元方法,以下是一些常用的元方法及其作用:
__index
:用于在访问一个表中不存在的字段时,返回一个默认值。__newindex
:用于在给表中不存在的字段赋值时,执行一些额外的逻辑。__add
:用于两个值相加时的操作。__sub
:用于两个值相减时的操作。__mul
:用于两个值相乘时的操作。__div
:用于两个值相除时的操作。__mod
:用于两个值取模时的操作。__pow
:用于计算一个值的 n 次方时的操作。__tostring
:用于将一个值转换为字符串时的操作。
以下是一个元表示例:
Copy Codemeta = {
__index = function(table, key)
print("accessing unknown field '" .. key .. "'")
return 0
end,
__newindex = function(table, key, value)
if key == "name" then
print("set name to '" .. value .. "'")
else
print("set unknown field '" .. key .. "' to '" .. tostring(value) .. "'")
end
rawset(table, key, value)
end,
__add = function(a, b)
return a + b
end,
__tostring = function(a)
return "Value:" .. a
end
}
t1 = {}
setmetatable(t1, meta)
t1.a = 1
t1.b = 2
t1.name = "test"
print(t1.a, t1.b, t1.c)
print(t1.name)
print(t1 + 1)
print(t1)
上述代码中,创建了一个名为 meta 的元表,并设置了其 __index、__newindex、__add 和 __tostring 等元方法。通过 setmetatable 函数将 t1 的元表设置为 meta。
当访问 t1 中不存在的字段 c 时,会触发 __index 元方法,输出 "accessing unknown field 'c'" 并返回默认值 0。当给 t1 中不存在的字段 d 赋值时,会触发 __newindex 元方法,输出 "set unknown field 'd' to '4'"。当给 t1 的 name 字段赋值时,会触发 __newindex 元方法,输出 "set name to 'test'"。当计算 t1 加 1 的结果时,会触发 __add 元方法,输出 2。当将 t1 转换为字符串时,会触发 __tostring 元方法,输出 "Value:table: 0x7fd2f0800480"。