-- __index和__newindex都是在访问table中不存在的项时会被调用的;
--当对一个table中不存在的索引赋值时,解释器就会查找__newindex元方法。如果有就调用它,而不是直接赋值。
--如果这个元方法指向一个table(此例是指向函数,但函数里面使用_t),Lua将对此table(_t)赋值,而不是对原有的table(agency_t)赋值
local _t = t --保持对原有table的私有访问。
local agency_t = {} --创建代理
--创建元表
local mt = {
__index = function(table,key)
print("access to element " .. tostring(key))
return _t[key] --通过访问原来的表返回字段值,如果注释此句话,agency_t[2]为nil(__index方法也没有对应的)
--如果把_t换成table,程序陷入了死循环
end,__newindex = function(table,key,value)
print("update of element " .. tostring(key) .. " to " .. tostring(value))
_t[key] = value
--更新原来的table,如果把_t换成table,程序陷入了死循环。
--因为agency_t[2]这个元素本来就不存在表中,然后这里不断执行进入__newindex,陷入了死循环
--rawset( table, key, value )来设置没有这个key的元素,
--lua table中__newindex的默认实现就是调用了rawset(绕过元方法)函数
end}
setmetatable(agency_t, mt)
agency_t[2] = "hello" --调用__newindex
print("+--------------------------------------+")
print(agency_t[2]) --有就调用它,而不是直接赋值
print("+--------------------------------------+")
print(rawget(agency_t,agency_t[2])) --rawget绕过元方法,直接访问
print("+--------------------------------------+")
print(t[2]) --没有使用元方法,所以没进入mt
结果:
>lua -e "io.stdout:setvbuf 'no'" "Lua.lua"
update of element 2 to hello
+--------------------------------------+
access to element 2
hello
+--------------------------------------+
access to element 2
nil
+--------------------------------------+
hello
>Exit code: 0