setmetatable备忘

【作为metatable的对象才需要__index和__newindex,对象本身加上__index和__newindex没啥意义】

 

访问对象的成员, 如果成员不存在, 就会去metatable对象的__index上去找, 而不是直接去metatable对象上找

1 local a = {}
2 local mt = { str="123" }
3 setmetatable(a, mt)
4 
5 print(a.str) --这边是nil, 因为不是在metatable对象本身上面找

 下面的是对的

1 local a = {}
2 local mt = { str="123" }
3 mt.__index = mt --是在metatable的对象的__index上找
4 setmetatable(a, mt)
5 
6 print(a.str) --这样就对了

也可以这样

local a = {}

local mt = { str="123" }
a.__index = mt
setmetatable(a, a)

或者这样 

1 local a = {}
2 
3 local mt = { str="123" }
4 setmetatable(a, { __index = mt })

 

__newindex也是如此,设置对象的成员时, 如果成员不存在, 则到metatable对象的__newindex上去设置, 而不是直接在metatable对象上设置

 1 local a = {}
 2     
 3 local mt = { str="123" }
 4 setmetatable(a, mt)
 5 
 6 a.str = "456"
 7 print(mt.str) --这边是123, 因为metatable的__newindex此时还是nil
 8 
 9 mt.__newindex = mt
10 a.str = nil
11 a.str = "456" --成员不存在, 到metatable对象的__newindex上去设置
12 print(mt.str) --这边metable就被改掉了

 

【如果metatable对象没设置__index值,则就会拿到nil】

 1 function Test1()
 2     local obj = { a = 0 }
 3     local objMeta = { b = 1 }
 4 
 5     setmetatable(obj, objMeta)
 6 
 7     print(obj.a)
 8     print(obj.b) --obj对象没有b成员, 就会去metatable的__index上找, 但objMeta的__index值为nil, 所以得到的是nil
 9 end
10 Test1()

 

【__index为函数时】

 1 local obj = { a = 0 }
 2 local objMeta = { b = 1 }
 3 
 4 objMeta.__index = function(tb, key)
 5     print("__index")
 6 
 7     --return tb[key] --死循环爆栈
 8     return rawget(tb, key)
 9 end
10 
11 print(obj.a)
12 print(obj.b) --是nil不是1, 因为rawget(tb, key)这边的tb还是obj

输出:

1

nil

 

【__tostring的值为函数, 不能是table】

 

【参考】

Lua元表(Metatable) - 简书 (jianshu.com)

posted @ 2022-02-22 00:20  yanghui01  阅读(281)  评论(0编辑  收藏  举报