2013-05-11 52 views
6

我無法理解爲什麼會出現在這些之間的__index元方法的行爲,以實例的差異:的Lua元表不一致

A = { __index = A } 
function A:speak() 
    print("I'm an A") 
end 
An_A = setmetatable({},A) 
An_A:speak() 

會引發以下錯誤:lua: l.lua:8: attempt to call method 'speak' (a nil value)

雖然

B = { __index = function(t,key) return B[key] end } 
function B:speak() 
    print("I'm an B") 
end 
An_B = setmetatable({},B) 
An_B:speak() 

將按預期執行,輸出I'm an B


在試圖理解爲什麼這是我讀PIL的this部分的情況。它指出:

The use of the __index metamethod for inheritance is so common that Lua provides a shortcut. Despite the name, the __index metamethod does not need to be a function: It can be a table, instead. When it is a function, Lua calls it with the table and the absent key as its arguments. When it is a table, Lua redoes the access in that table.

我對此的理解是,在涉及片段「A」,__index = A導致表A做接入(按照上述報價的boldened segmenet)。如果是這種情況,我不明白爲什麼沒有找到與鍵"speak"相關的功能。爲了嘗試解決這個問題,我決定在B片段中實現函數方法,該片段返回B中與key相關的值,並且它工作正常。當然__index = A和(改編自B__index = function(t,key) return A[key] end具有相同的效果。

任何澄清將不勝感激。

回答

9

你的第一個例子發生了什麼事A.__index == nil。當你創建「A」在你的第一線位置:

A = { __index = A } 

的分配「A」的計算結果爲nil,因爲它沒有在這一點上還不存在的右側。其結果是,後來當您在此處設置的元表:

An_A = setmetatable({},A) 

它真的結束了做這個事情類似於:

An_A = setmetatable({}, {__index = nil}) 

爲了得到它的工作您想要的方式,你必須確保__index不是nil。例如,它分配表施工後:

A = {} 
A.__index = A 

function A:speak() 
    print("I'm an A") 
end 
An_A = setmetatable({},A) 
An_A:speak()    --> outputs I'm an A 
+0

謝謝你的偉大的解釋,並沒有出現我這種情況會發生,我曾以爲它會像其他一些語言,其中一些諸如'F = lambda n:f(n)'是有效的。歡呼:) – HennyH 2013-05-11 02:54:01

+1

@HennyH:'f =函數(n)返回f(n)結束'在盧阿罰款也是出於同樣的原因。相當於失敗的python是'd = {「__index」:d}',但python會'NameError' – Eric 2013-05-12 16:30:27

+0

@Eric我想任何遞歸函數都遵循相同的模式。 – HennyH 2013-05-12 22:55:57