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這個函數調用的說明,這個調用有點與其餘語言不同,參數沒有放在圓括號中」 函數名() 「,lua
而是直接跟了一個表的構造式,參看program in lua第五章 函數,最開始的前10句:spa
一個函數若只有一個參數,而且此參數是一個字面字符串或者是一個table構造式,那麼圓括號是無關緊要的.
指針
days = readOnly{"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}code
2:readOnly(t) 的形參 t,接收了 {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday」}對象
那麼至關於 t = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday」}blog
3:緊接着 local proxy = {} 是一個局部的表,且是空表,它的元表爲mt,是由於 setmetatable(proxy,mt)這句話。繼承
也就是說 proxy.__index = mt. __index這個字段是lua 爲表內置的.ip
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