學習傳送門:https://www.runoob.com/lua/lua-metatables.html
元表(metatable)
利用元表可以對兩個table進行操作,每個對table的操作提供了對應的元方法。
設置元表: setmetatable(table,metatable)
對指定 table 設置元表(metatable),如果元表(metatable)中存在 __metatable 鍵值,setmetatable 會失敗
獲取元表:getmetatable(table)
返回table對應的元表。
注:感覺很像給一個類設置子類(自我加深理解,哈哈哈哈)
元方法
(1)__index-----查找
A.metatable包含的是一個表格,當在table中查找一個key找不到,就會繼續在table對應的元表中查找,如果找到返回對應的值,找不到返回nil。
mytable=setmetatable({},{__index={lala=1,haha=2}})
print("lala-->"..mytable.lala) //輸出1
print("xixi-->"..mytable.xixi) //輸出nil,有些版本找不到會報錯
B.metatable包含的是一個方法,當在table查找一個key找不到,lua就會調用方法,將table和key傳入方法,如果找到返回對應的值,找不到返回nil。
mytable=setmetatable({},
{
__index=function(mytable,key)
if(key=="hello") then
return "hello"
else
return "nil"
end
end
})
print("hello-->"..mytable.hello) //輸出hello
print("haha-->"..mytable.haha) //輸出nil
(2)__newindex----賦值
A.給metatable元表賦值,給table中一個不存在的key賦值,會直接賦值到table的元表中,table無法訪問。
mymetatable={}
mytable=setmetatable({key1=2},{__newindex=mymetatable})
mytable.newkey=1 //給mymetatable元表增加新值
print("mymetatable.newkey-->"..mymetatable.newkey) //輸出 1
print("mytable.newkey-->"..mytable.newkey) //輸出nil,mytable無法訪問
mytable.key1=3 //更新mytable中原有key的值
print("mytable.key1-->"..mytable.key1) //輸出 3
print("mymetatable.key1-->"..mymetatable.key1) //輸出nil,元表無法訪問table中的key
B.給table賦值,用rawset方法(rawset(t, k, v)函數,它可以不涉及任何元方法而直接設置table t中與key k相關聯的value v,key如果是一個鍵,則必須是字符串的)
mytable=setmetatable({key1=2},
{
__newindex=function(mytable,key,value)
rawset(mytable,key,value)
end
})
mytable.newkey=4
print("mytable.newkey-->"..mytable.newkey) //輸出 4
注:table和metatable在__newindex元方法中,自己的表只能自己訪問,他是賦值不是查找
(3)表操作符
注:不是很明白表操作符的元方法,直接用一個方法傳兩個table進去操作不是更直接方便嗎,爲什麼要用元表(沒想明白)
(4)__call----調用一個值時調用
(5)__tostring---修改表的輸出行爲
後面這幾個元方法我覺得都可以用方法實現,但是相信既然是元方法肯定有他的妙處吧。
南投北浪 2020/06/28