学习传送门:https://www.runoob.com/lua/lua-metatables.html
元表(metatable)
利用元表可以对两个table进行操作,每个对table的操作提供了对应的元方法。
设置元表: setmetatable(table,metatable)
对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败
获取元表:getmetatable(table)
返回table对应的元表。
注:感觉很像给一个类设置子类(自我加深理解,哈哈哈哈)
元方法
(1)__index-----查找
A.metatable包含的是一个表格,当在table中查找一个key找不到,就会继续在table对应的元表中查找,如果找到返回对应的值,找不到返回nil。
mytable=setmetatable({},{__index={lala=1,haha=2}})
print("lala-->"..mytable.lala) //输出1
print("xixi-->"..mytable.xixi) //输出nil,有些版本找不到会报错
B.metatable包含的是一个方法,当在table查找一个key找不到,lua就会调用方法,将table和key传入方法,如果找到返回对应的值,找不到返回nil。
mytable=setmetatable({},
{
__index=function(mytable,key)
if(key=="hello") then
return "hello"
else
return "nil"
end
end
})
print("hello-->"..mytable.hello) //输出hello
print("haha-->"..mytable.haha) //输出nil
(2)__newindex----赋值
A.给metatable元表赋值,给table中一个不存在的key赋值,会直接赋值到table的元表中,table无法访问。
mymetatable={}
mytable=setmetatable({key1=2},{__newindex=mymetatable})
mytable.newkey=1 //给mymetatable元表增加新值
print("mymetatable.newkey-->"..mymetatable.newkey) //输出 1
print("mytable.newkey-->"..mytable.newkey) //输出nil,mytable无法访问
mytable.key1=3 //更新mytable中原有key的值
print("mytable.key1-->"..mytable.key1) //输出 3
print("mymetatable.key1-->"..mymetatable.key1) //输出nil,元表无法访问table中的key
B.给table赋值,用rawset方法(rawset(t, k, v)函数,它可以不涉及任何元方法而直接设置table t中与key k相关联的value v,key如果是一个键,则必须是字符串的)
mytable=setmetatable({key1=2},
{
__newindex=function(mytable,key,value)
rawset(mytable,key,value)
end
})
mytable.newkey=4
print("mytable.newkey-->"..mytable.newkey) //输出 4
注:table和metatable在__newindex元方法中,自己的表只能自己访问,他是赋值不是查找
(3)表操作符
注:不是很明白表操作符的元方法,直接用一个方法传两个table进去操作不是更直接方便吗,为什么要用元表(没想明白)
(4)__call----调用一个值时调用
(5)__tostring---修改表的输出行为
后面这几个元方法我觉得都可以用方法实现,但是相信既然是元方法肯定有他的妙处吧。
南投北浪 2020/06/28