首页 > 代码库 > 元表(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)