Lua元表(__index方法個人理解)

什麼是Lua元表:

原表可理解爲“一個方法表(類似函數表)“,裏面包含了一些解決方案。當一個table設置元表之後,相當於關聯了這個方法表

  • setmetatable(table,metatable): 對指定 table 設置元表(metatable),如果元表(metatable)中存在 __metatable 鍵值,setmetatable 會失敗。
  • getmetatable(table): 返回對象的元表(metatable)。

實例:

mytable = {} ;                                          -- 普通表
mymetatable = {} ;                                  -- 元表
setmetatable(mytable,mymetatable);     -- 把 mymetatable 設爲 mytable 的元表

以下爲返回對象元表:

getmetatable(mytable)                            -- 這回返回mymetatable

 

元表中有很多原方法,下面以__index元方法爲例:

當你通過鍵來訪問 table 的時候,如果這個鍵沒有值,那麼Lua就會尋找該table的metatable(假定有metatable)中的__index 鍵。如果__index包含一個表格,Lua會在表格中查找相應的鍵。

例如:

house = {house_computer = "Macbook"};
company = {company_computer = "Acer"};
setmetatable(house, company);                  --把company設置爲house的metatable
print(house.company_computer);

輸出的結果是nil

 

把代碼改爲:

house = {house_computer = "Macbook"};
company = {company_computer = "Acer"};
company.__index = company;       -- 把company的__index方法指向自己
setmetatable(house, company);    --把company設置爲house的metatable
print(house.company_computer);

輸出的結果是Acer

在剛學習時,對__index方法有所誤解:如果house 的元表是company ,如果訪問了一個house中不存在的成員,就會訪問查找company中有沒有這個成員。而這個理解實際上是錯誤的,即使將house的元表設置爲company,而且company中也確實有這個成員,返回結果仍然會是nil,原因就是company的__index元方法沒有賦值。之前有說過,原表類似於“方法表”,設置元表相當於關聯了方法表,但是並不是在方法表裏查找元素,而應該是調用方法表裏相應的方法。__index就是定義了當表在查找相應的key值對應的value時,查找失敗,應該怎麼辦。

把代碼改爲:

house = {house_computer = "Macbook"};
company = {company_computer = "Acer"};
company.__index = function()
                    return "hello world!";
                    end
setmetatable(house, company);    --把company設置爲house的metatable
print(house.company_computer);

輸出的結果是hello world!

在上述例子中,訪問house.company_computer時,house中沒有company_computer這個成員,但Lua接着發現house有元表company,注意:此時,Lua並不是直接在company中找名爲company_computer的成員,而是調用company的__index方法,如果__index方法爲nil,則返回nil,如果是一個表,那麼就到__index方法所指的這個表中查找名爲company_computer的成員,於是,最終找到了company_computer成員。__index方法除了可以是一個表,還可以是一個函數,如果是一個函數,__index方法被調用時將返回該函數的返回值。

 

總結

Lua 查找一個表元素時的規則,其實就是如下 3 個步驟:

  • 1.在表中查找,如果找到,返回該元素,找不到則繼續
  • 2.判斷該表是否有元表,如果沒有元表,返回 nil,有元表則繼續。
  • 3.判斷元表有沒有 __index 方法,如果 __index 方法爲 nil,則返回 nil;如果 __index 方法是一個表,則重複 1、2、3;如果 __index 方法是一個函數,則返回該函數的返回值。

該部分內容來自作者寰子:https://blog.csdn.net/xocoder/article/details/9028347

注:別的元方法也一樣,調用的是實際上是設置的元表的元方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章