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 ...
随机推荐
- django静态html中做动态变化
在搭建网站中经常有筛选分类的需求 在django中为了简便,我们经常将某些相同部分的内容取出来单独存放形成一个base模板,其他的template继承这个base就可以使用其中的内容 但是这些相同的部 ...
- ElasticSearch中设置排序Java
有用的链接:http://stackoverflow.com/questions/12215380/sorting-on-several-fields-in-elasticsearch 有的时候,需要 ...
- Angularjs中的拦截器 (卧槽,好牛逼)
$httpAngularJS 的 $http 服务允许我们通过发送 HTTP 请求方式与后台进行通信.在某些情况下,我们希望可以俘获所有的请求,并且在将其发送到服务端之前进行操作.还有一些情况是,我们 ...
- 通过Linux定时任务实现定时轮询数据库及发送Http请求
通过Linux定时任务实现定时轮询数据库及发送Http请求 概述 有时需要临时增加一个定时任务(需要根据数据库查询结果然后发送HTTP请求),如果在项目中额外增加(Java+Spring+Quartz ...
- Haproxy 8种算法+Session共享
Haproxy有8种负载均衡算法(balance),分别如下: 1.balance roundrobin # 轮询,软负载均衡基本都具备这种算法 2.balance static-rr # 根据权重, ...
- XP如何在桌面新建宽带连接的快捷方式
1 打开控制面板,点击网络和Internet连接 2 如果存在宽带连接选项. 则点击左侧的网上邻居,然后点击查看网络连接 右击宽带连接,点击创建快捷方式,放到桌面,改一下快捷方式的名字即可. 3 ...
- js控制div内的滚动条的位置
通过div的scrollTop变动控制垂直滚动条位置. 通过div的scrollLeft变动控制水平滚动条位置. 示例: <body> //d1是外层div,带滚动条 <div id ...
- asp.net core mvc视频A:笔记3-1.视图基本用法
常用介绍 注意:ViewBag是对View的封装,所以如果两者键值(Key)是一样的话,后者会覆盖前者. 新建项目,添加空控制器 小技巧-快速添加视图 控制器方法,使用ViewData和ViewBag ...
- ASP.NET CORE RAZOR :个性化显示
https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/da1 我们的电影应用有个不错的开始,但是展示效果还不够理想. 我 ...
- E - Hangover(1.4.1)
Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Submit cid=1006#sta ...