Luaルックアップテーブル要素プロシージャ(メタテーブル、_indexメソッドがどのように動作するか)

2583 ワード

LuaテーブルはHashMapに似ています
Luaの表の本質は実はHashMapのようなもので、その要素は多くのKey-Value対で、1つの表に存在しない要素にアクセスしようとすると、Luaの検索メカニズムがトリガーされ、このメカニズムによって「継承」のような行為をシミュレートしたのです
例:
local tempTable = {}
tempTable.memberB = "test"
print(tempTable.memberA) --      tempTable       memberA
print(tempTable.memberB) 

--[[
nil
test
]]

nilとして出力される理由は簡単で、tempTableにはmemberAというメンバーはいません.これは私たちが普段HashMapに対する認識に合っています.しかしLuaテーブルではtempTableにメタテーブルがあれば状況は異なる.
メタテーブルとは:
メタテーブルは「操作ガイド」のようなもので、一連の操作の解決策が含まれています.例えば_indexメソッドは、このテーブルがインデックスに失敗した場合にどうするかを定義します.
local tempTable = {}
tempTable.memberB = "test"
---__index    key       
setmetatable(tempTable, { __index = function()
    return "not find"
end })

print(tempTable.memberA)
print(tempTable.memberB)
--[[
not find
test
]]

__indexメタメソッド:
AのメタテーブルがBであれば、Aに存在しないメンバーにアクセスすると、Bにそのメンバーがいるかどうかを検索するという誤解が多い.この理解は完全に間違っていますが、実際には、AのメタテーブルをBに設定しても、Bにこのメンバーが確かに存在していても、結果はnilになります.理由はBの__です.indexメタメソッドには値が割り当てられていません.私たちが前に言ったことを忘れないでください:“メタテーブルは1つの操作ガイドです”、メタテーブルを定義して、ただ操作ガイドがあって、しかし操作ガイドの中で要素を探すべきでなくて、_indexメソッドは、「操作ガイド」の「インデックスが失敗した場合、どうすればいいか」です.そういえばちょっと回りますね.したがって、
栗を挙げる:)
father = {
    house=1
}
son = {
    car=1
}
setmetatable(son, father) -- son metatable   father
print(son.house)

出力の結果はnilです.
コードを
father = {
    house=1
}
father.__index = father --  father index      
son = {
    car=1
}
setmetatable(son, father)
print(son.house)

出力の結果は1で、予想通り
__indexメタメソッドの意味
このように、上記の例と併せて、_indexメタメソッドの意味:
上記の例では、sonにアクセスする.houseの時、sonにはhouseというメンバーはいませんでしたが、Luaは次にsonにメタテーブルfatherがあることに気づき、
注意:この場合、Luaは直接fatherの中でhouseという名前のメンバーを探すのではなく、fatherを呼び出す_indexメソッド、もし_indexメソッドがnilの場合はnilを返し、テーブル(前例のfatherの__indexメソッドが自分に等しい場合)であれば_Indexメソッドが指すこのテーブルでhouseという名前のメンバーを検索し、最終的にhouseメンバーを見つけました.
注意:_indexメソッドは、テーブルのほかに関数であってもよいし、関数であれば_indexメソッドが呼び出されると、関数の戻り値が返されます.
father.__index = function()
    return "i am function"
end

Luaがテーブル要素を検索する3つのステップ
ここで、Luaがテーブル要素を検索する際のルールをまとめると、実は次の3つのステップがあります.
1.テーブルで検索し、見つかった場合は要素を返し、見つからない場合は続行します.
2.このテーブルにメタテーブルがあるかどうかを判断し(操作ガイド)、メタテーブルがない場合はnilを返し、メタテーブルがある場合は続行する
3.メタテーブル(操作ガイド)にインデックス失敗に関するガイド(すなわち__indexメソッド)があるかどうかを判断し、ない場合(すなわち__indexメソッドがnil)はnilを返す.もし__indexメソッドはテーブルであり、1、2、3を繰り返す.もし__indexメソッドが関数である場合、その関数の戻り値を返します.
サンプルコード:https://github.com/zhaoqingqing/blog_samplecode/tree/master/lua_scripts/metatable
転載自:寰子https://blog.csdn.net/xocoder/article/details/9028347