在Lua中,一个表可以通过key访问到对应的value,但是无法直接对两个表进行操作。因此,Lua提供了元表(metable),它允许改变表的行为,而每个行为都会有对应的元方法。
一、理解Lua元表
Lua中,元表的表现行为类似与C++中的操作符重载。比如,我们可以通过重载__add
元方法,来计算两个Lua数组的并集,如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| local set1 = {1,3,5,6} local set2 = {2,4,6}
local union = function(self, another) local set = {} local result = {}
for k,v in pairs(self) do set[v] = true end
for k,v in pairs(another) do set[v] = true end
for k,v in pairs(set) do table.insert(result,v) end
return result end
setmetatable(set1, { __add = union })
local set = set1 + set2 for _, v in pairs(set) do print(v) end
|
其运行结果为:
当我们对两个表进行相加操作时,Lua的执行流程如下:
在这里,我们将key为“__add
”的元素的值称为元方法。
二、设置元表
通过setmetatable函数,我们可以为一个表设置元表,如下示例:
1 2 3 4 5
| local mt = {} local t = {}
local res = setmetatable(t, mt) print(type(res), res)
|
以上代码可以简写为:
1 2
| local res = setmetatable({}, {}) print(type(res), res)
|
其执行结果为:
1
| table table: 0x564da1a6ef00
|
我们可以看到,setmetatable函数并不会直接修改原表,然是会返回一个新表
三、获取元表
通过getmetatable函数,我们可以获取到一个表的元表,如下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| local t = {1,2,3} local res = getmetatable(t) print(type(res), res) print()
local mt = {2,4,6} local t = {1,3,5} local t = setmetatable(t, mt) for k,v in pairs(t) do print(k,v) end print()
for k,v in pairs(getmetatable(t)) do print(k,v) end
|
其执行结果为:
1 2 3 4 5 6 7 8 9
| nil nil
1 1 2 3 3 5
1 2 2 4 3 6
|
我们可以看到,一个表的元表并不能直接被访问到,需要借助getmetatable方法。