第一版是针对 Lua 5.0 编写的。虽然对于后续版本来说仍然非常相关,但还是有一些区别。
第四版针对 Lua 5.3,可在 Amazon 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 13 章。元表和元方法 |
__index
和 __newindex
仅在表中不存在索引时才相关。捕获对表的所有访问的唯一方法是保持表为空。因此,如果我们想要监视对表的全部访问,我们应该为真实表创建一个代理。此代理是一个空表,具有适当的 __index
和 __newindex
元方法,它们会跟踪所有访问并将它们重定向到原始表。假设 t
是我们要跟踪的原始表。我们可以编写类似这样的代码
t = {} -- original table (created somewhere) -- keep a private access to original table local _t = t -- create proxy t = {} -- create metatable local mt = { __index = function (t,k) print("*access to element " .. tostring(k)) return _t[k] -- access the original table end, __newindex = function (t,k,v) print("*update of element " .. tostring(k) .. " to " .. tostring(v)) _t[k] = v -- update original table end } setmetatable(t, mt)此代码会跟踪对
t
的每次访问
> t[2] = 'hello' *update of element 2 to hello > print(t[2]) *access to element 2 hello(请注意,遗憾的是,此方案不允许我们遍历表。
pairs
函数将在代理上运行,而不是在原始表上运行。)
如果我们想要监视多个表,我们不需要为每个表使用不同的元表。相反,我们可以将每个代理与它的原始表相关联,并为所有代理共享一个公共元表。将代理与表相关联的一种简单方法是将原始表保存在代理的字段中,只要我们能确保该字段不会用于其他目的即可。确保这一点的一种简单方法是创建一个私钥,其他人无法访问。将这些想法放在一起,得到以下代码
-- create private index local index = {} -- create metatable local mt = { __index = function (t,k) print("*access to element " .. tostring(k)) return t[index][k] -- access the original table end, __newindex = function (t,k,v) print("*update of element " .. tostring(k) .. " to " .. tostring(v)) t[index][k] = v -- update original table end } function track (t) local proxy = {} proxy[index] = t setmetatable(proxy, mt) return proxy end现在,每当我们想要监控一个表
t
时,我们所需要做的就是 t = track(t)
。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |