metatable与metamethod

元表metatable

metatable允许我们改变table的行为,每个行为关联了对应的元方法。

  • setmetatable(table,metatable):对指定table 设置元表(metatable),如果元表中含有键__metatable , setmetatable则会失败。记得 返回值是table
  • getmetatable(table):返回对象的元表(metatable)。

设置元表

mytable = {}                  
mymetatable = {}                  
setmetatable(mytable,mymetatable)   -- 等同于mytable = setmetable({} , {})
getmetatable(mytable)               -- 返回mymetatable,就是mytable的元表
元方法metamethod

__index metatable最常用的键,对表访问。
查找一个表元素的规则可以归纳为如下几个步骤:

  • Step1:在表自身中查找,如果找到了就返回该元素,如果没找到则执行Step2
  • Step2:判断该表是否有元表(操作指南),如果没有元表,则直接返回nil,如果有元表则继续执行Step3
  • Step3:判断元表是否设置了有关索引失败的指南(__index元方法),如果没有(__index为nil),则直接返回nil;如果有__index方法是一张表,则重复执行Step1->Step2->Step3;如果__index方法是一个函数,则返回该函数的返回值
-- 继续承接上面的代码
mymetatable.__index={ foo = 3 }    -- 设置元方法__index为table
print(mytable.foo)
-- 输出 
-- 3

__index当做函数处理

mytable     = { key1 = "C#" }
mymetatable = { __index =   function(table,key)
								if(key == "key2") then
									return "Java"
								else
									return "Lua"
								end
							 end}
setmetatable(mytable , mymetatable)
print(mytable.key1 , mytable.key2 , mytable.key3)
-- 输出 
-- C# Java Lua

__newindex 用来对表更新(__index用来对表访问)。
当你给表的一个缺少的索引赋值,编译器就会查找__newindex元方法:如果存在则调用这个函数而不进行赋值操作。

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
-- 输出 
-- value1
-- nil    新值2
-- 新值1  nil

以上实例中表设置了元方法 __newindex,在对新索引键(newkey)赋值时(mytable.newkey = “新值2”),会调用元方法,而不进行赋值。而如果对已存在的索引键(key1),则会进行赋值,而不调用元方法 __newindex。

__call 允许给table调用一个值时调用。

mytable = setmetatable({} , {
    __call = function (mytable,key)
        if(key == 1) then
            print("111")
        else
            print("222")
        end                                    
    end
})
mytable(1)
mytable(2)
-- 输出
-- 111
-- 222

当给mytable传入参数1时,这里会调用其元表中的__call元方法。元方法中定义的table就是代指普通表mytable,而key指的就是调用table时传入的参数,这里就是1。后面的逻辑就能搞懂了。

__tostring 用于修改表的输出行为。

mytable = setmetatable( {10 , 20 , 30 } , {
    __tostring = function (table)
        sum = 0
        for _ , v in ipairs(table) do
            sum = sum + v
        end
        return "表中所有元素之和"..sum
    end
})
print(mytable)
-- 输出
-- 表中所有元素之和60

__add 对应的运算符 ‘+’

mytable={"Lua","Java","C","C#","C++"}--普通表
mymetatable={
--两表相加将新表中的元素添加到mytable中去
  __add=function (tab,newtab)
     local mi=0
     for k,v in pairs(tab) do
        if (k>mi)then
            mi=k
        end
     end

     for k,v in pairs(newtab) do
        mi=mi+1
        table.insert(tab,mi,v)
     end
     return tab
  end
}--元表  元表扩展了普通表的行为

mytable=setmetatable(mytable,mymetatable)--给指定的表设定元表
newtab={"PHP","Phthon"}
--其中只要有一个表设置了元表都可以实现加法
v=mytable+newtab  
for k,v in pairs(v) do
   print(k,v)
end
-- 输出
--Lua
--Java
--C
--C#
--C++
--PHP
--Phthon
元方法描述
__sub对应的运算符 ‘-’
__mul对应的运算符 ‘*’
__div对应的运算符 ‘/’
__mod对应的运算符 ‘%’
__unm对应的运算符 ‘-’
__concat对应的运算符’…’
__eq对应的运算符’==’
__lt对应的运算符’<’
__le对应的运算符’<=’
__metatable保护元表
__concat(a, b)连接
__unm(a)相反数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值