lua 元表是个啥?
1 function readOnly(t) 2 local proxy = {} 3 local mt = { 4 __index = t, 5 __newindex = function(t,k,v) 6 error("attempt to update a read-only table") 7 end 8 } 9 setmetatable(proxy,mt) 10 return proxy 11 end 12 13 days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"} 14 print(days[1]) 15 days[2] = "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 + 1] = e end return "{" .. table.concat(l,", ") .. "}" end function Set.print(s) print(Set.tostring(s)) end s1 = Set.new{10,20,30,40,} s2 = Set.new{30,1} 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
posted on 2015-02-10 16:25 EarlyBird 阅读(3541) 评论(0) 编辑 收藏 举报