第一版是為 Lua 5.0 所寫的。雖然在很大程度上仍然適用於後續版本,但仍有一些差異。
第四版針對 Lua 5.3,可在 Amazon 和其他書店購買。
購買這本書,您也可以協助 支援 Lua 專案。
![]() |
用 Lua 進行程式設計 | ![]() |
第 II 部分。表格和物件 第 13 章。元表格和元方法 |
__index
元方法我之前說過,當我們存取表格中不存在的欄位時,結果會是 nil。這句話沒錯,但並非全部。實際上,此類存取會觸發直譯器尋找 __index
元方法:如果沒有此方法(通常如此),則存取結果會是 nil;否則,元方法會提供結果。
這裡的典型範例是繼承。假設我們要建立數個描述視窗的表格。每個表格都必須描述數個視窗參數,例如位置、大小、色彩配置等。所有這些參數都有預設值,因此我們希望建立視窗物件,只提供非預設參數。第一個替代方案是提供一個建構函式,填入不存在的欄位。第二個替代方案是安排新的視窗從原型視窗繼承任何不存在的欄位。首先,我們宣告原型和一個建構函式函數,建立共用元表格的新視窗
-- create a namespace Window = {} -- create the prototype with default values Window.prototype = {x=0, y=0, width=100, height=100, } -- create a metatable Window.mt = {} -- declare the constructor function function Window.new (o) setmetatable(o, Window.mt) return o end現在,我們定義
__index
元方法
Window.mt.__index = function (table, key) return Window.prototype[key] end在該程式碼之後,我們建立一個新視窗,並查詢不存在的欄位
w = Window.new{x=10, y=20} print(w.width) --> 100當 Lua 偵測到
w
沒有要求的欄位,但有一個具有 __index
欄位的元表格時,Lua 會呼叫此 __index
元方法,並以 w
(表格)和 "width"
(不存在的鍵)作為引數。然後,元方法會使用指定的鍵索引原型,並傳回結果。
將 __index
元方法用於繼承非常普遍,因此 Lua 提供了一個捷徑。儘管名稱為 __index
,但 __index
元方法不需要是函數:它可以是一個表格。當它是函數時,Lua 會使用表格和不存在的鍵作為其引數來呼叫它。當它是表格時,Lua 會在該表格中重新執行存取。因此,在我們之前的範例中,我們可以將 __index
宣告為
Window.mt.__index = Window.prototype現在,當 Lua 尋找元表的
__index
欄位時,它會找到 Window.prototype
的值,它是一個表格。因此,Lua 會重複在這個表格中的存取,也就是執行等同於
Window.prototype["width"]這會給出想要的結果。
將表格用作 __index
元方法提供了一個實作單一繼承的便宜且簡單的方法。函式雖然比較昂貴,但提供了更大的彈性:我們可以實作多重繼承、快取和許多其他變化。我們將在 第 16 章 討論這些繼承形式。
當我們想要存取表格而不呼叫其 __index
元方法時,我們會使用 rawget
函式。呼叫 rawget(t,i)
會對表格 t
進行原始存取。執行原始存取不會加速您的程式碼(函式呼叫的開銷會抵消您可能獲得的任何好處),但有時您需要它,我們稍後會看到。
版權所有 © 2003–2004 Roberto Ierusalimschy。保留所有權利。 | ![]() |