首页 > 代码库 > 元表(metatable)
元表(metatable)
元表为重定义Lua中任意一个对象(值)的默认行为提供了一种公开入口. 如同许多OO语言的操作符重载或方法重载.
算术类元方法: 字段:__add __mul __ sub __div __unm __mod __pow (__concat)
代码:(两个table相加)
下例中mt是元表,__add是元方法
tA = {1, 3}tB = {5, 7} --tSum = tA + tBmt = {} mt.__add = function(t1, t2) for _, item in ipairs(t2) do --这里的_可以改成任意字符 table.insert(t1, item) endreturn t1end setmetatable(tA, mt) --定义table tA的重载运算符_add setmetatable(只能用于table) tSum = tA + tB for k, v in pairs(tSum) do print(v)end
输出:
1
3
5
7
关系类元方法: 字段:__eq __lt(<) __le(<=),
--比较集合大小 <mt = {}function mt.__lt(tA, tB) return #tA < #tBend tA, tB = {3}, {1, 2} setmetatable(tA, mt)setmetatable(tB, mt) print(tA < tB)
#是表的长度运算符
比如
local a = {4,5,6,7,8}
print(#a)
会输出5
相当于table.getn(a)
在Lua本身提供的功能中, 不允许你改变除了table类型值外的任何其他类型值的Metatable, 除非使用C扩展或其他库. setmetatable和getmetatable是唯一一组操作table类型的Metatable的方法.
关于__index:
__index元方法:
按照之前的说法,如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员。这个过程大体是这样,但却不完全是这样,实际上,即使将A的元表设置为B,而且B中也确实有这个成员,返回结果仍然会是nil,原因就是B的__index元方法没有赋值。按照我的理解,__index方法是用来确定一个表在被作为元表时的查找方法
father = { house=1 } son = { car=1 } setmetatable(son, father) --把son的metatable设置为father print(son.house)
输出的结果是nil,但如果把代码改为
father = { house=1 } father.__index = father -- 把father的__index方法指向自己 son = { car=1 } setmetatable(son, father) print(son.house)
输出的结果为1,符合预期
在上述例子中,访问son.house时,son中没有house这个成员,但Lua接着发 现son有元表father,于是此时father被当做元表来查找,此时,Lua并不是直接在father中找名为house的成员,而是调用 father的__index方法,如果__index方法为nil,则返回nil,如果是一个表(上例中father的__index方法等于自己,就 是这种情况),那么就到__index方法所指的这个表中查找名为house的成员,于是,最终找到了house成员。
注:__index方法除了可以是一个表,还可以是一个函数,如果是一个函数,__index方法被调用时将返回该函数的返回值。
元表(metatable)