類別與方法 |
|
資料表可用作關聯性陣列。此功能允許我們在類別表中儲存函式,亦即將函式名稱對應至函式。
A = {} function A:add(x,y) return x+y end print( A:add(1,2) ) -- prints 3
A
類別實例。如果我們想建立另一個實例,我們可以建立一個資料表 be(例如 B={}
),並將 A
中的所有方法複製至 B
。
可以使用 Lua 的標籤方法建立類別的多個實例。這些標籤方法可用於將來自類別實例的函式要求重新導向至類別函式表。亦即我們不再需要將所有類別函式複製至類別的每個實例。例如:
-- settag() returns a table "{}" which has been tagged with a new tag value A = settag({},newtag()) -- use the index tag method to redirect a request for a function to the -- class function table settagmethod(tag(A),"index", function(t,f) return %A[f] end) function A:new(x,y) -- create an instance of class A local t = {x=x,y=y} settag(t,tag(A)) -- tag the new table to tell it what its class type is return t end function A:add() print (self.x+self.y) end function A:sum(a) assert(tag(self)==tag(a)) -- check they are same class print (self.x+a.x,self.y+a.y) end a = A:new(7,9) -- new instance of A a:add() b = A:new(2,4) -- new instance of A b:add() a:sum(b) -- "sum" of 2 instances
a:sub()
,將導致堆疊溢位,因為 Lua 會無限尋找未識別的函式,然後標籤方法回傳的 nil
。這可以使用 rawget(table,key)
來修正,從函式表中擷取函式。rawget()
在從資料表中取得鍵值時不會呼叫任何標籤方法。settagmethod(tag(A),"index", function(t,f) return rawget(%A,f) end)
a.number = 123
a:number() -- try and call x
a.sum = 7 print( a.sum ) -- should this print <function> or 7 ? (it prints 7)
這個問題無法解決,因為呼叫請求不會告知標籤方法需要哪種類型。我們可以選取一個優先選項,例如優先使用類別實例值,而非函式表值。(這麼做我們可以支援函式重載)。
如果函式表優先,我們可以使用取得資料表標籤方法,在函式表 A
中先檢查一個方法是否存在,例如:
settagmethod(tag(A), "gettable", function(t,k) if rawget(%A,k) then return rawget(%A,k) else return rawget(t,k) end end )
統一方法:Edgar Toernig 在 Sol(Lua 的分支版本)中透過導入統一方法解決了這個問題。在此,函式/方法表與標籤相關聯。發生資料表查詢時會發生什麼事,取決於查詢的呼叫方式。亦即 a.foo
和 a:foo
有不同的含意。a.foo
尋找一個稱為「foo」的成員,而 a:foo
在標籤的函式表中尋找「foo」方法。因此,您可以擁有兩個成員,一個是資料,一個是函式,愉快地並排共處,沒有衝突。
t.foo
和 t:foo
之間的問題(並允許儲存任意資料)嗎?這看起來像是現有的 Lua 標籤方法系統,還是經過修改過的?我不認為這只是嘗試模擬 Python 的結果,這裡存在衝突。也就是說,你的實作受到了限制。我原本以為 meta 機制應該是靈活到足以實作這個功能的。這是實作風格的問題嗎?這個問題可以使用獨立函式來避免,但我不認為那是很簡潔的做法(而且在這個範例中,不像 Python)––NDT
operator[]
或專門的成員函式。欄位存取和非欄位存取之間沒有模糊地帶。Lua 的標籤方法很有限。你無法區分 table[x]
用於存取欄位,以及 table.x
/ table:x
用於呼叫方法。你Python 字典問題有一個簡單的解決辦法,就是放棄使用原生的表格語法來存取元素,並依賴 get
和 set
等方法。這也會讓實作簡單得多!––JohnBelmonte