本文主要擴展了元表和__index和__newindex用法
元表裏面有這樣一句話
- setmetatable(table,metatable): 對指定 table 設置元表(metatable),如果元表(metatable)中存在 __metatable 鍵值,setmetatable 會失敗。
我證明一下
ta = {"1","2","3"}
ma = {"小明","李華","wei"}
se = setmetatable(ta,ma)
print(getmetatable(ta)[1])
print("se"..se[1])
輸出
小明
se1
>Exit code: 0
下面是我添加__metatable 注意:前面是兩個下劃線
ta = {"1","2","3"}
ma = {"小明","李華","wei"}
ma.__metatable = "ss"
se = setmetatable(ta,ma)
print(getmetatable(ta)[1])
print("se"..se[1])
輸出:
nil
se1
這樣就說明了setmetatable會失敗,然後就獲取不到元表了,個人理解應該是這個意思
使用__metatable可以保護元表,禁止用戶訪問元表中的成員或者修改元表。
__index 元方法查看錶中元素是否存在,如果不存在,返回結果爲 nil;如果存在則由 __index 返回結果。
後面可以是一個方法,還可以是一個數組
__index = function(tab,key)
return "不存在"
end
當你給表的一個新的索引賦值,解釋器就會查找__newindex 元方法:
mytable = {"C++","C","Java","C#"}
Mymetatable = {
__newindex = function(tab,key,value)
print("我們修改了"..key.."修改爲"..value)
end
}
mytable = setmetatable(mytable,Mymetatable)
mytable[1] = "ca"
mytable[5] = "haha"
mytable[1] = "meme"
print(mytable[1])
只輸出了5那個
>lua -e "io.stdout:setvbuf 'no'" "yuanbiao2.lua"
我們修改了5修改爲haha
meme
>Exit code: 0
以上實例中表設置了元方法 __newindex,在對新索引鍵(newkey)賦值時(mytable.newkey = "新值2"),會調用元方法,而不進行賦值。而如果對已存在的索引鍵(key1),則會進行賦值,而不調用元方法 __newindex。
如果我們想進行賦值操作
Mymetatable = {
__newindex = function(tab,key,value)
print("我們修改了"..key.."修改爲"..value)
rawset(tab,key,value)
end
}
重點是那一行 rawset(tab,key,value)
__newindex 還有一種用法,如果後面跟的是一個表,我們新加的數據會加到表裏面,如果沒有__newindex 會加到原來的mytable中
mytable = {"C++","C","Java","C#"}
newtable = {}
Mymetatable = {
__newindex = newtable
}
mytable = setmetatable(mytable,Mymetatable)
mytable[1] = "ca"
mytable[5] = "haha"
mytable[1] = "meme"
print(mytable[1])
print(mytable[5])
print(newtable[5])
輸出:
>lua -e "io.stdout:setvbuf 'no'" "yuanbiao2.lua"
meme
nil
haha
>Exit code: 0
總結:
__newindex 元方法用來對錶更新,__index則用來對錶訪問 。
__newindex 更新的表是__newindex指向的表,就是當我們發現,主表不存在的鍵時候,我們會把鍵值賦值給__newindex指向的表,也就是上面那個代碼中的newtable。
__index 就是如果不存在的鍵,會訪問__index 根據__index的指向進行返回。
擴展:__mode = "kv"
這是弱表的一個用法,學習的話可以進行參考:https://blog.csdn.net/shimazhuge/article/details/40310233,感謝大佬吧。
起主要應用就是不要的時候,讓值或者鍵等於nil,這樣,就把他給清理掉了 。