chapter 13_4 跟踪table的访问
__index和__newindex都是在table中没有所需访问的index时才发挥作用。
因此,只有将一个table保持为空,才有可能捕捉到所有对它的访问。为了监视一个table的所有访问,就应该为真正的table创建一个代理。
这个代理就是一个空的table,其中__index和__newindex元方法可用于跟踪所有的访问,并将访问重定向到原来的table上。
假设我们要跟踪table t 的访问,可以这样做:
t = {} --original table, 在其他地方创建的
local _t = t --保持对原table的一个私有访问
t = {} --创建一个代理
local mt = {
__index = function (t,k)
print("*access to elemet " .. tostring(k))
return _t[k] --访问原table中的k
end
__newindex = function(t,k,v)
print("*update of element" .. tostring(k) .. " to " .. tostring(v))
_t[k] = v --更新原table的值
end
}
setmetatable(t,mt) --将mt设置为 t 的元表
这段代码跟踪了所有对 table t 的访问:
t[] = "hello" -- *update of element 2 to hello
print(t[]) --> hello -- *access to element 2
但是上面的例子有一个问题,就是无法遍历原来的table。函数pairs只能操作代理table,而无法访问原来的table。
可以通过定义__pairs去遍历:
mt.__pairs = function()
return function(_,k)
return next(_t,k)
end
end
如果想要同时监视几个table,无须为每个table创建不同的元表。相反,只要以某种形式将每个代理与其原table关联起来,
并且所有代理都共享一个公共的元表。这个问题与前一节所讨论的将table与其默认值相关联的问题类似。
例如将原来table保存在代理table的一个特殊字段中,如下:
local index = {} --创建私有索引
local mt = { --创建元表
__index = function(t,k)
print("*access to element " .. tostring(k)
return t[index][k] --访问原来的table
end
__newindex = function(t,k,v)
print("*update of element " .. tostring(k) .. " to " .. tostring(v))
t[index][k] = v --更新原来的table
end
__pairs = function(t)
return function(t,k)
return next(t[index],k)
end , t
end
}
function track(t)
local proxy= {}
proxy[index] = t
setmetatable(proxy,mt)
return proxy
end
现在,若要监视table t ,唯一要做的就是执行:
t = track(t)
只读的table
通过代理的概念,可以很容易地就实现出只读的table,只需跟踪所有对table的跟新操作,并引发一个错误就可以了。
由于无须跟踪查询访问,所以对于__index元方法可以直接使用原table来代替函数。这也更简单,并且在重定向所有查询到原table时效率也更高。
不过,这种做法要求为每个只读代理创建一个新的元表,其中__index指向原来的table。
function readOnly(t)
local proxy = {}
local mt = {
__index =t ,
__newindex = function(t,k,v)
error("*attempt to update a read-only table",)
end
}
setmetatable(proxy,mt)
return proxy
end
下面是一个使用的示例,创建了一个表示星期的只读table:
days = readOnly{"Sunday","Monday","Tuesday","Thursday","Friday","Saturday"}
print(days[]) -->Sunday
days[] = "Noday" -- > stdin:1: attempt to update a read-only table
以上内容来自:《Lua程序设计第二版》和《Programming in Lua third edition 》
chapter 13_4 跟踪table的访问的更多相关文章
- lua的table元类
Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表达式a+b.当Lua试图将两个table相加时, ...
- [转]LUA元表
lua元表和元方法 <lua程序设计> 13章 读书笔记 lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在 ...
- lua元表和元方法 《lua程序设计》 13章 读书笔记
lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在创建table时不会创建元表. t = {} print(getmet ...
- lua metatable和metamethod元表和元方法
Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表达式a+b.当Lua试图将两个table相加时, ...
- Lua 程序设计 (Roberto,Ierusalimschy 著)
1 开始 2 类型与值 3 表达式 4 语句 5 函数 6 深入函数 7 迭代器与泛型for 8 编译,执行与错误 9 协同程序(coroutine) 10 完整的示例 11 数据结构 12 数据文件 ...
- lua学习笔记(八)
元表与元方法 基本概念 1.lua中每个值都有一个元表 2.table和userdata可以有各自独立的元表 3.其它类型的值共享其类型所属的单一 ...
- Step By Step(Lua元表与元方法)
Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6 获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 ...
- Dapper,大规模分布式系统的跟踪系统--转
原文地址:http://bigbully.github.io/Dapper-translation/ 概述 当代的互联网的服务,通常都是用复杂的.大规模分布式集群来实现的.互联网应用构建在不同的软件模 ...
随机推荐
- 使用rsync无密码传输
众多数据库服务器的管理过程中,在不同服务器间的文件传输是免不了的.您可以使用scp命令或FTP方法完成文件的发送和接收,这篇文章我将给大家介绍另外一种方法,这就是rsync命令.rsync是文件传输程 ...
- #大数加减乘除#校赛D题solve
#include<iostream> #include<cstdio> #include<cstring> #include<string> #incl ...
- Hadoop之MapReduce分布式计算
简单介绍一下项目背景——很简单,作死去接下老师的活,然后一干就是半个月,一直忙着从零基础到使用Hadoop中的MapReduce来解决一个实际问题,也就是用来计算一个数据量较大的二度朋友关系. 那么首 ...
- 搭建Gitlab
这个周末好奇想搭建一个私有的Gitlab,以前折腾过一次.现在记录如下. 一.安装Ubuntu 16.04 LTS server amd64 到Virtual Box 二.安装gitlab服务器 按照 ...
- 原生JavaScript+CSS3实现移动端滑块效果
在做web页面时,无论PC端还是移动端,我们会遇到滑块这样的效果,可能我们往往会想着去网上找插件,其实这个效果非常的简单,插件代码的的代码往往过于臃肿,不如自己动手,自给自足.首先看一下效果图: 分析 ...
- <密码的实现>输入密码的时候,显示“*”,而不是显示输入内容
一开始还以为用C语言和C++不能实现输入密码的时候显示出“*”而不显示输入的内容呢!没想到偶然的机会试出了用while循环结构可以实现.以下是我整理的C语言和C++的代码,供初学者参考. 这是C语言实 ...
- 手机浏览器wap网页点击链接触发颜色区块的问题解决办法
引子 在做HTML5 WAP网页的时候,一行内容做了2个链接,点击一个标签的时候,整个颜色块会闪一下,影响美观.需求针对这种情况来问我,能否把这个一闪的颜色去掉.我当时就想,这个怎么去?那我也不好直接 ...
- 关于scanf()函数的一点理解
习惯了c++的cin.cout之后,也不怎么关注空格,反正cin.cout会自动处理.有一次实验,创建Huffman树,要求输入空格字符,当时就懵逼了.cin咋输入空格呢? 没办法,只能重新用scan ...
- 《C程序设计语言》 squeeze函数(从字符串s中删除字符c)
squeeze void squeeze(char string[], int ch) { int i, j; ; string[i] != '\0'; i++) { if (string[i] != ...
- response.setContentType与 request.setCharacterEncoding 区别
1.request.setCharacterEncoding()是设置从request中取得的值或从数据库中取出的值的编码 2.response.setContentType指定 HTTP 响应的编码 ...