lua元表和元方法 《lua程序设计》 13章 读书笔记
lua中每個(gè)值都有一個(gè)元表,talble和userdata可以有各自獨(dú)立的元表,而其它類型的值則共享其類型所屬的單一元表。lua在創(chuàng)建table時(shí)不會創(chuàng)建元表。
t = {} print(getmetatable(t)) --顯示過元表 此時(shí)是nil--可以用setmetatable來設(shè)置或修改任何table的元表 t1 = {} setmetatable(t,t1) assert(getmetatable(t) == t1)任何table可以作為任何值的元表,而一組相關(guān)的table可以共享一個(gè)通用的元表,此元表描述了一個(gè)共同的行為。一個(gè)tabel甚至可以作為它自己的元表,用于描述其特有行為。
在lua中,只能設(shè)置table的元表。要設(shè)置其它類型的元表,必須通過C代碼來完成
print(getmetatable("hi")) --005DECD8 說明字符串有元表 print(getmetatable(10)) --number沒有元表13.1? 算術(shù)類的元方法
Set = {} --集合local mt = {} --集合元表--根據(jù)參數(shù)列表中的值創(chuàng)建一個(gè)新的集合 function Set.new(l)local set = {}setmetatable(set,mt) --指定 table set的元表為mtfor k,v in ipairs(l) doset[v] = true --注意,是拿索來當(dāng)數(shù)據(jù)用的endreturn set end function Set.union(a,b)local res = Set.new{}for k,v in pairs(a) do res[k] = true endfor k,v in pairs(b) do res[k] = true endreturn res endfunction Set.intersection(a,b)local res = Set.new{}for k,v in pairs(a) doif b[k] thenres[k] = trueendendreturn res endfunction Set.tostring(set)local l = {}for k,v in pairs(set) dol[#l + 1] = kendreturn "{" .. table.concat(l,", ") .. "}" endfunction Set.print(s)print(Set.tostring(s)) end--將元方法加入元表 mt.__add = Set.union --指定加號為求并集的方法 mt.__mul = Set.intersection --指定乘號為交集的方法 s1 = Set.new{11,22,31,44,56} s2 = Set.new{66,33,22,31} s3 = s1 + s2 --求并集 Set.print(s3) --輸出 {11, 31, 66, 22, 33, 56, 44} s4 = s1 * s2 --求交集 Set.print(s4) --輸出 {31, 22}13.2 關(guān)系類元方法
關(guān)系是指 __eq(等于)、__lt(小于)等
mt.__le = function(a,b)for k in pairs(a) doif not b[k] then return false endendreturn true endmt.__lt = function(a,b)return a<=b and not (b<=a) endmt.__eq = function(a,b)return a<=b and b<=a endss1 = Set.new{2,4} ss2 = Set.new{4,10,2} print(ss1<=ss2) --true print(ss1<ss2) --true print(ss1>=ss1) --true print(ss1>ss1) --false print(ss1 == ss2*ss1) --true13.3 庫定義的元方法
tostring是一個(gè)典型的實(shí)例。它能將各種類型的值表示為簡單的文本格式
print({}) ----table: 003ECEF0函數(shù)總是調(diào)用tostring來格式化輸出。當(dāng)格式化任意值時(shí),tostring會檢測該值是否有一個(gè) __tostring元方法。如果有,他就調(diào)用這個(gè)方法用來作為tostring的返回值
在集合實(shí)例中,我們定議了將任命表示為字符串的方法,我們可以設(shè)置元表的__tostring字段
mt.__tostring = Set.tostring sstext = Set.new{33,55,6666} print(sstext) --{55, 33, 6666}假設(shè)想要保護(hù)集合的元表,使用戶即不能看也不能修改集合的元表。那么就需要用到__metatable。當(dāng)設(shè)置了該字段時(shí),getmetatable就會返回這個(gè)字段的值,而setmetatable會引發(fā)一個(gè)錯(cuò)誤
mt.__metatable = "not your business" sstext1 = Set.new{} print(getmetatable(sstext1)) --not your business setmetatable(s1,{})13.4 table 訪問的元方法
13.4.1 __index元方法
當(dāng)訪問一個(gè)table中不存在的字段中時(shí),如果這個(gè)字段不存在得到nil,但是如果這個(gè)table有一個(gè)元方法__index那么如果沒有這個(gè)字段,就由這個(gè)元方法來提供結(jié)果
Window = {}Window.prototype = {x=0,y=0,width = 100,height = 100} Window.mt = {}function Window.new(o)setmetatable(o,Window.mt)return o end--現(xiàn)在定義一個(gè)元方法 Window.mt.__index = function(table,key)return Window.prototype[key] endw = Window.new{x=10,y=20} print(w.width) -- 100 window實(shí)際上沒有width這個(gè)字段__index元方法還可以是一個(gè)table
13.4.2? __newindex元方法
與__index不同的是__index是在查詢的時(shí)候用的而_newindes是在更新的時(shí)候用的
13.4.3具有默認(rèn)值的table
以下代碼為table設(shè)置默認(rèn)值
function setDefault(t,d)local mt = {__index = function() return d end}setmetatable(t,mt) end13.4.4 跟蹤table的訪問
__index和__newindex都是在table中沒有所需的index才發(fā)揮作用。因?yàn)橹挥衪able保持空才能捕捉到所有對他的訪問,為了監(jiān)視一個(gè)table的所有訪問就得為真正的 table 創(chuàng)建一個(gè)代理
?
t_src = {} --要跟蹤的表 local _t = t_srct = {} --創(chuàng)建代理--創(chuàng)建元表 local mt = {__index = function(t,k)print("*access to element " .. tostring(k))return _t[k]end,__newindex = function(t,k,v)print("*update of element " .. tostring(k) .. " to " .. tostring(v))_t[k] = vend } setmetatable(t,mt)t[2] = "hello" -- *update of element 2 to hello print(t[2]) --*access to element 213.4.5 只讀的table
只讀table與上一節(jié)跟蹤table類似,是通過__newindex來限制修改table內(nèi)存
出處:http://www.cnblogs.com/zhangdongsheng/ 作者:張東升總結(jié)
以上是生活随笔為你收集整理的lua元表和元方法 《lua程序设计》 13章 读书笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: monkey测试===如何获取andro
- 下一篇: AJAX的post请求与上传文件