--[[
今天学习lua中的元表,书上讲的太难懂了,网上搜索教程也将的模模糊糊,
搜了一会总结了一下经验,跟大家分享一下,希望对您有所帮助。
--]]
--如何设置元表?
local t = {}
local mt = {}
getmetatable(t)--nil
setmetatable(t,mt)--将t1设置为t的元表
getmetatable(t)--0xb67660
-- __add元表方法
local a = {v = 100}
local b = {v = 300}
local mt = {}
mt.__add = function(a,b)
return a.v + b.v
end
setmetatable(a,mt)
print(a+b)
--运行结果
400
--[[
__index和__newindex元表方法
"index": 索引 table[key]。 当 table 不是表或是表 table 中不存在key 这个键时,这个事件被触发。
此时,会读出 table 相应的元方法。尽管名字取成这样, 这个事件的元方法其实可以是一个函数也可以是一张表。
如果它是一个函数,则以 table 和 key 作为参数调用它。如果它是一张表,最终的结果就是以 key 取索引这
张表的结果。(这个索引过程是走常规的流程,而不是直接索引, 所以这次索引有可能引发另一次元方法。
"newindex": 索引赋值 table[key] = value 。 和索引事件类似,它发生在 table 不是表或是表 table 中不存在
key 这个键的时候。 此时,会读出 table 相应的元方法。同索引过程那样, 这个事件的元方法即可以是函数,也可以是一张
表。 如果是一个函数, 则以 table、 key、以及 value 为参数传入。如果是一张表, Lua 对这张表做索引赋值操作。
(这个索引过程是走常规的流程,而不是直接索引赋值, 所以这次索引赋值有可能引发另一次元方法。)一旦有了 "newindex"
元方法, Lua 就不再做最初的赋值操作。(如果有必要,在元方法内部可以调用 rawset 来做赋值。
]]
-- __index和__newindex函数
local mt = {
mt.__index = function(t, k)
print("call index function",t,k)
end
mt.__newindex = function(t,k,v)
print("call new index function",t,k,v)
end
mt.__call = function(f,...)
print(...)
end
local data = {}
setmetatable(data,mt)
local a = data.a
data.a = 10
--运行结果
call index function table: 0x1905660 a
call new index function table: 0x1905660 a 10
-- __index和_newindex表
local a = {10,20,30,40,50}
local b = {100,200,300,400,500}
local mt = {}
local t = {}
setmetatable(t,mt)
mt.__index = a
mt.__newindex = b
print(t[1]) -- 10
print(t[3]) -- 30
t[1] = 999
t[2] = 888
print(b[1]) -- 999
print(b[2]) -- 888
--运行结果
10
30
999
888
总结:
local a = data.a --t.a此处调用t表中的a键值,没有找到这个键值,mt元表中就会触发__index元表方法。
data.a = 100 --t.a此处进行赋值,没有找到这个键值,mt元表中就会触发__newindex元表方法。
我们再来写一个只读元表
function read_only_table(t)
local a = {}
local mt = {__index = t,__newindex = function()
error("readonly table") end}
setmetatable(a,mt)
return a
end
local value=read_only_table{10,20,30,40,50,60}
--这里的read_only_table{10,20,30,40,50,60}等价于rad_only_table({10,20,30,40,50,60})
print(value[1])
value[1] = 55555
--运行结果
10
lua: main.lua:4: readonly table
stack traceback:
[C]: in function 'error'
main.lua:4: in metamethod '__newindex'
main.lua:11: in main chunk
[C]: in ?