lua表访问跟踪
当访问一个 table 或者更新 table 中的某个元素时,lua 首先会在 table 查找是否存在该元素,如果没有,就会查找 table 是否存在 index(访问) 或者 newindex(更新) 原方法。以访问为例,首先在 table 中查找某个字段,如果不存在,解释器会去查找 index 这个原方法,如果仍然没有,返回 nil。所以说,index 和 __newindex 是在 table 中没有所需访问的 index 时才发挥作用的。
根据上面这种思路,如果我们想跟踪一个 table 的操作行为,那么需要一个空表,每次对这个空表操作的时候,就会使用 index 或者 newindex 这些元方法,在元方法中对原始 table 进行访问和操作,并打印跟踪信息。而之前创建的那个空表,就是代理。
---------------------------------------------
print "跟踪单个表"
local _t = {}
local mt = {
__newindex = function(t, name, value)
print("__newindex", name, value)
–rawset(_t, name, value) --原始访问 不访问原表
_t[name] = value
end,
__index = function(t, name)
print("__index", name, value)
--return rawget(_t, name) --原始访问 不访问原表
return _t[name]
end
}
–a.__index = a
local a = {}
setmetatable(a, mt)
a.x = 1
print(a.x)
print "跟踪多个表"
local index = {} – 创建私有索引,即原表在代理表中特殊字段
local mt = {
__index = function (t, k)
print("__index " … tostring(k))
return t[index][k]
end,
__newindex = function (t, k, v)
print("__newindex " … tostring(k) … " to " … tostring(v))
t[index][k] = v
end
}
function track (t)
local proxy = {}
proxy[index] = t
setmetatable(proxy, mt)
return proxy
end
local ori_table = {} --在其他地方创建的原表,对他进行跟踪
local _o = track(ori_table)
_o[2] = "lua"
print(_o[2])