2017-10-14 15 views
2

我學習和Lua的面向對象編程。我無法理解在實例的__index字段中分配表格併爲實例設置metatable之間的功能差異。我回顧了官方Lua的參考手冊,但我沒有完全掌握它們的區別。例如,要創建Account類的實例,它將Account類(self)的__index字段設置爲自身,然後將實例的metatable設置爲Account類。和元表

function Account:new (o) 
    o = o or {} 
    self.__index = self 
    setmetatable(o, self) 
    return o 
end 

這是怎麼回事?在這種情況下,爲什麼Account設置自己的索引?如果實例「o」僅使用Account類作爲其metatable,那麼在這種情況下真正使用metatables有什麼用處?爲什麼Lua允許類爲其實例的metatables?

從我的理解,元表應該是隻包括元方法(__newindex,__index,__add等)表。但這個例子有__index爲Account類的領域,它通過這一點,是不是元表並沒有一個元表分配給它使得分配查找另一元表,如果是有道理的。

在此先感謝。

回答

2

在該示例中,Account是元表,並且o是實例。由於Account被用作一類,它需要一個__index字段來定義規則的方法。該__index場在構造函數中定義的,因爲調用構造函數的行爲意味着Account被用來爲一類。

既然是有些多餘在構造函數中定義__index,你經常會看到這樣的例子:

Account = {} 
Account.__index = Account 

function Account:new (o) 
    o = o or {} 
    setmetatable(o, self) 
    return o 
end 

我無法理解的__index領域分配表之間的功能差異一個實例併爲該實例設置一個metatable。

您通常不會在實例中放入__index。 (儘管在PiL示例中,任何對象都可能被用作另一個類,請謹慎使用。)爲該實例設置元方法是將metamethods應用於該實例的。

從我的理解中,metatables應該是僅由metamethods組成的表(__newindex,__index,__add等)。

上有什麼可元表包含沒有限制,但是一個表需要定義至少一個元方法的元表使用時有任何效果。

Metamethods基本上提供操作符重載。這意味着metatables可以爲其他表定義行爲。 __index是面向對象的真正重要的元方法,因爲這就是我們如何使用實例來訪問類中定義的方法和變量。

爲什麼metatable的__index通常指向自己?否則,我們需要另一個表來保存常規方法。對於簡單的OOP框架,讓一個表執行這兩項工作更容易。

簡短回答:metatable爲實例定義metamethods。 __index是將字段訪問路由到另一個表的元方法(如果__index是一個表,它也可以是一個函數)。

+0

謝謝您的快速回答。關於分配「帳戶.__索引=帳戶」,我是否正確地說這隻在我期望用戶創建帳戶實例時才需要,否則,分配不需要? – bladematthewslp

+0

是的。我不知道有任何其他理由要這樣做。 – luther

+1

好的,謝謝!這有助於很多。我現在終於明白了。我來自C++/Java/C#背景,所以Lua的面向對象設計版本需要對思維方式進行一些調整。 – bladematthewslp