Lua 元表(Metatable)学习笔记

什么是元表?

在 Lua 中,每个值都可以有一个元表(metatable)。元表是一个 Lua 表,其中存储了一些元方法(metamethods)。当 Lua 需要对一个值执行特定的操作时,如果该值具有元表,则会查找元表中是否有对应操作的元方法。如果找到了对应的元方法,Lua 就会调用该元方法来完成操作。

如何设置元表?

通过 Lua 的 setmetatable 函数可以设置一个值的元表。setmetatable 函数接受两个参数:第一个参数是需要设置元表的值,第二个参数是元表。例如:

Copy Code
local t1 = {1, 2, 3} local mt = {} setmetatable(t1, mt)

上述代码创建了一个名为 t1 的表,并将其元表设置为 mt。

常用的元方法

Lua 中定义了许多元方法,以下是一些常用的元方法及其作用:

  • __index:用于在访问一个表中不存在的字段时,返回一个默认值。
  • __newindex:用于在给表中不存在的字段赋值时,执行一些额外的逻辑。
  • __add:用于两个值相加时的操作。
  • __sub:用于两个值相减时的操作。
  • __mul:用于两个值相乘时的操作。
  • __div:用于两个值相除时的操作。
  • __mod:用于两个值取模时的操作。
  • __pow:用于计算一个值的 n 次方时的操作。
  • __tostring:用于将一个值转换为字符串时的操作。

以下是一个元表示例:

Copy Code
meta = { __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"。