lua 元表是个啥?
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 days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
print(days[])
days[] = "Noday"
—关于上面的只读表的运行过程解释
1:首先readOnly这个函数调用的说明,这个调用有点与其他语言不一样,参数没有放在圆括号中” 函数名() “,
而是直接跟了一个表的构造式,参看program in lua第五章 函数,最开始的前10句:
一个函数若只有一个参数,并且此参数是一个字面字符串或者是一个table构造式,那么圆括号是可有可无的.
days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}
2:readOnly(t) 的形参 t,接收了 {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday”}
那么相当于 t = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday”}
3:紧接着 local proxy = {} 是一个局部的表,且是空表,它的元表为mt,是因为 setmetatable(proxy,mt)这句话。
也就是说 proxy.__index = mt. __index这个字段是lua 为表内置的.
4:紧接着 return proxy 那么就相当于 days = proxy,记住 proxy是空表
5:print(days[1]) 相当于print(proxy[1]) ,但由于proxy[1]没有值,于是找它的元表 mt,而mt也没有 mt[1]对应的值,于是又找到__index 字段对应的值,于是就找到了之前t接收的匿名元表,然后就输出了Sunday,匿名元表就是{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday”}
6:当对其赋值时,同第5步一样,最终找到了__newindex, 而它的值是一个函数,于是执行了
error("attempt to update a read-only table”)
7:上面的分析过程,就是lua解释这个脚本的过程,我们想象成,自己写了一个函数,当它接收那样一段脚本时,是像上面那样执行这么一个逻辑,把这么一个逻辑用一个概念总结,称之为元表,这就是元表的内函.
8:那为什么要这样做呢?这个逻辑,实际上是面向对象语言中的,多态的逻辑。只不过像C++,这样的语言,把上面的这种寻找过程的代码,由编译器产生而已。多态是相对继承而言的,即父类指针,指向了子类的对象,在运行时发生的行为,与代码给我们的字面逻辑不一致.
9:lua通过元表,来模拟面象对象的多态特性。
--输出结果为:
--[[
Sunday
lua: d:/test.lua:6: attempt to update a read-only table
stack traceback:
[C]: in function 'error'
d:/test.lua:6: in function <d:/test.lua:5>
d:/test.lua:15: in main chunk
[C]: ?
]]—
//-------------------------接下来分析一下 program in lua 第十三章的 13.1“算术类的元方法”------------------
把代码里加了点打印语句,就好理解了,另外把for语句省掉的部分写完整了。这样对照结果,就不会迷糊了。
对于初学者来说,原版书写的真是有点"不够厚道"。我看了N遍.才明白.不过省掉应该是为了少返回值,少执行一些代码,提高效率吧。
Set = {}
local mt ={}
function Set.new (l)
local set = {}
setmetatable(set, mt)
for _, v in ipairs(l) do
print("<",_,">","(",v,")")
set[v] = true
end
return set
end
function Set.union(a,b)
local res = Set.new{}
for k ,v in pairs(a) do res[k] = true print(k,res[k]) end
for k ,v in pairs(b) do res[k] = true print(k,res[k]) end
return res
end
function Set.intersection (a,b)
local res = Set.new{}
for k in pairs(a) do
res[k] = b[k]
end
return res
end
function Set.tostring (set)
local l = {}
for e ,v in pairs(set) do
print(e,"|----|", v)
l[#l + ] = e
end
return "{" .. table.concat(l,", ") .. "}"
end
function Set.print(s)
print(Set.tostring(s))
end
s1 = Set.new{,,,,}
s2 = Set.new{,}
print(getmetatable(s1))
print(getmetatable(s2))
mt.__add = Set.union
s3 = s1 +s2
print('-------')
print(s3)
print('-------')
Set.print(s3)
print(getmetatable(""))
for n in pairs(_G) do print(n) end
lua 元表是个啥?的更多相关文章
- [转]LUA元表
lua元表和元方法 <lua程序设计> 13章 读书笔记 lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在 ...
- 学习Lua setmetatable Lua 元表
Lua 元表(Metatable) 在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作. 个人理解,这个相当于其他语言的继承,是把这个类的方法 ...
- Step By Step(Lua元表与元方法)
Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...
- lua元表与元方法
lua中提供的元表(metatable)与元方法(metamethod)是一种非常重要的语法,metatable主要用于做一些类似于C++重载操作符式的功能. lua中提供的元表是用于帮助lua变量完 ...
- lua元表和元方法 《lua程序设计》 13章 读书笔记
lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在创建table时不会创建元表. t = {} print(getmet ...
- lua元表
__index元方法:按照之前的说法,如果A的元表是B,那么如果访问了一个A中不存在的成员,就会访问查找B中有没有这个成员.这个过程大体是这样,但却不完全是这样,实际上,即使将A的元表设置为B,而且B ...
- <6>Lua元表和冒号 self
Lua中没有像C.C++.JAVA中的类概念,面向对象等 ,但我们可以模拟出来 1. Lua中有个很重要的概念元表 设置元表setmetatable()函数 获取元表getmetatable()函数 ...
- lua元表学习
a = {, } b= {, } vector2 = {} function vector2.Add(v1, v2) if(v1 == nil or v2 == nil)then return nil ...
- [转]lua元表代码分析
http://lin-style.iteye.com/blog/1012138 版本整理日期:2011/4/21 元表其实就是可以让你HOOK掉一些操作的一张表. 表的定义在ltm.h/c的文件里.对 ...
- lua元表详解
元表的作用 元表是用来定义对table或userdata操作方式的表 举个例子 local t1 = {1} local t2 = {2} local t3 = t1 + t2 我们直接对两个tabl ...
随机推荐
- ElasticSearch 安装中文分词器
1.安装中文分词器IK 下载地址:https://github.com/medcl/elasticsearch-analysis-ik 在线下载安装: elasticsearch-plugin.bat ...
- kibana显示elasticsearch集群中flume到入的日志
日志通过flume导入elasticsearch集群见这里:flume 日志导入elasticsearch kibana介绍 kibana主页 kibana是一个功能强大的elasticsearch数 ...
- lua基础【三】唯一数据结构table表
--[[ 数据结构table对象(一种动态分配的对象) lua中的表操作.table类型实现了"关联数组的". "关联数组是一种具有特殊索引方式的数组" 能够通 ...
- ddmrp
DDMRP 特点 在供应链加入 mts 缓冲,解耦 lead time, 缩小 bullwhip 效应,最小化库存 buffer动态调整 buffer 分3个颜色共 4个区域[zone],为 gree ...
- Android 热修复使用Gradle Plugin1.5改造Nuwa插件
随着谷歌的Gradle插件版本号的不断升级,Gradle插件如今最新的已经到了2.1.0-beta1,相应的依赖为com.android.tools.build:gradle:2.0.0-beta6, ...
- linux标准输入输出错误输出
Linux Shell 环境中支持输入输出重定向,用符号"<"和">"来表示.0.1和2分别表示标准输入.标准输出和标准错误信息输出,可以用来指定需 ...
- jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因
jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因 今天利用了jquery.validate.js来验证表单,发现在火狐.谷歌浏览器当中都可以进行验证,但是在IE系列浏 ...
- java调用本地默认浏览器
1 http://blog.csdn.net/casularm/article/details/3401018 2
- sprint3 【每日scrum】 TD助手站立会议第七天
站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 在日历各个事件上都增加闹钟显示,并将数据传递给日程和时间表 调整闹钟和整个项目的显示效果,最后做出了微信界面滑动的显示效果 闹钟在广播协议的时 ...
- C的字符串操作接口实现
近期在写一个关于用HTTP控制storm的的UI功能.已经实现完毕,採用在nginx里面增加相应的模块调用来实现,模块中调用一个动态载入的SO.这个SO用THRIFT和zookeeper client ...