lua元表的相關知識
阿新 • • 發佈:2018-12-21
setmetatable()和getmetatable():
local a=8 local b = "s" local t = {1,2} --在Lua程式碼中,只能設定table的元表。若要設定其它型別的值得元表,則必須通過C程式碼來完成 --對於字串,標準的字串程式庫為所有的字串都設定了一個元表,而其它型別在預設情況下都沒有元表 print(getmetatable(t)) --輸出nil print(getmetatable(b)) --輸出table: 0042EA68 print(getmetatable(a)) --輸出nil local t2 = {} setmetatable(t,t2) --將t2設定為t的元表 print(getmetatable(t)) --輸出table: 0026B120 --setmetatable(a,t2) --print(getmetatable(a)) --報錯 /在 Lua 程式碼中,通過呼叫setmetatable 來設定且只能設定 table 的元表 setmetatable(b,t2) print(getmetatable(b)) --報錯 /在 Lua 程式碼中,通過呼叫setmetatable 來設定且只能設定 table 的元表
元方法__metatable:
Set = {} local mt = {} --根據引數列表中的值建立一個新的集合 function Set.New(T) local set = {} setmetatable(set,mt) for _ ,v in pairs(T) do set[v]=true end ----使用__metatable可以保護元表,禁止使用者訪問元表中的成員或者修改元表 mt.__metatable = "can not get the metatable" return set end local tb = Set.New({1,2,3}) --將mt設定為tb的元表 print(tb) print(getmetatable(tb)) --輸出can not get the metatable local test = {1,2} setmetatable(test,mt) print(getmetatable(test)) --輸出can not get the metatable --setmetatable(tb,{}) --報錯cannot change a protected metatable 輸出"can not get the metatable"
元方法__add:
--------------元方法 __add local mt ={} --定義一個元方法 mt.__add = function (t1,t2) local temp = {} for i, v in pairs(t1) do table.insert(temp,v) end for i, v in pairs(t2) do table.insert(temp,v) end return temp end local t1 = {1,2,3} local t2 = {3,5} setmetatable(t1,mt) --設定mt為t1的元表 local t3 = t1+t2 --將兩個table相加 for i, v in pairs(t3) do print(v) --輸出1 2 3 3 5 end --程式執行順序: --lua中兩個table原本是無法做相加操作的,但是可以通過__add元方法實現 --先查詢t1中是否有對應的元表,若有看看是否定義了__add元方法。如果有則運算 --沒有則查詢t2中是否有對應的元表,再看看是否定義了__add元方法,有則運算,沒有報錯
元方法__index:
---
windows = {}
windows.default = {x=0,y=0,color = {r=255,g=255,b=125}}
windows.mt = {} --建立元表
--宣告new函式
function windows.new(o)
setmetatable(o,windows.mt)
return o
end
--定義__index元方法 對應的是一個有引數的函式
windows.mt.__index = function(table,key)
return windows.default[key]
end
local www = windows.new({x=10,z=30})
--print(www.x) --輸出10
--print(www.y) --輸出 0
--print(www.color.r) --輸出 255
other1 = {hhh = 666}
other2 ={mmm=333,ppp=999,hhh=5555}
setmetatable(other2,other1)
--定義__index元方法 對應的是一個table
other1.__index =other1
print(other2.hhh) --輸出666
print(other2.jjj) --輸出nil
--定義__index元方法 對應的是一個沒有引數的函式
--function setDefault(tb,defaultValue)
-- local mt = {__index = function()return defaultValue end}
-- setmetatable(tb,mt)
--end
--tb1 = {x=10,y=20}
--setDefault(tb1,100)
--print(tb1.x) --輸出 10
--print(tb1.z) --輸出100
--print(tb1.k) --輸出100
--程式執行順序:
--通過鍵來訪問table時,如果table中沒有這個鍵,那麼lua就會查詢該table是否有元表
--元表中是否定義了__index元方法,若__index對應的是一個函式,那麼lua就會呼叫這個函式,
--table和鍵作為引數傳給函式;
--若__index對應的是一個table,那麼lua就在這個table中查詢對應的鍵
元方法__newindex:
---
local smartMan = {
name = "king",
sayhello = function()
print("你媽喊你回家吃飯")
end
}
local t1 = {kkk = "7"}
--t1.name = "5"
local mt ={
--__index = smartMan,
__newindex = function(table,key,value)
print("你媽喊你回家拖地")
rawset(table,key,value)
end,
}
setmetatable(t1,mt)
t1.kkk = 6
print(t1.kkk) -- 輸出 6
t1.kkk = "5"
t1.ggg = "000" --新增一個索引
print(t1.kkk) --輸出 你媽喊你回家拖地 5
-- __newindex元方法用於索引更新
rawget()和rawset():
--rawset(table,index,value)
--在不呼叫元表的情況下,給table[index]賦值為value
--就是說就算該table有元表,這個函式也會讓元方法失去作用
local m1 = {x=1,y=2}
local m2 = {z=3}
setmetatable(m1,m2)
m2.__index = m2
print(m1.z) --輸出3
rawset(m1,"z",5)
print(m1.z) --輸出 5
--rawget(table,index)
--不呼叫元表,獲取table真正的值table[index]
local m3 = {x=1,y=2}
local m4 = {x=6,z=8}
setmetatable(m3,m4)
m4.__index = m4
print(m3.x) --輸出 1
print(m3.z) --輸出 8
local zhi= rawget(m3,"z")
print(zhi) --輸出nil
元方法總彙: 後續若有在專案中碰到其他元方法再補上。