原表解析
在 Lua table 中我們可以訪問對應的 key 來得到 value 值,但是卻無法對兩個 table 進行操作(比如相加)。
因此 Lua 提供了元表(Metatable),允許我們改變 table 的行為,每個行為關聯了對應的元方法。
- setmetatable(table,metatable): 對指定 table 設置元表(metatable),如果元表(metatable)中存在 __metatable 鍵值,setmetatable 會失敗。
- getmetatable(table): 返回對象的元表(metatable)。
原表的定義
mytable={} --普通表
mymetatable={} --元表
setmetatable(mytable,mymetatable) --將mymetatable設置為mytable的原表--可簡寫如下:
mytable=setmetatable({},{})getmetatable(mytable) --會返回mytable的元表
原表的應用
1. 變量賦值
解析如下:
mymetatable={}
mytable=setmetatable({k1="v1"},{__newindex=mymetatable})mytable.newkey="v2"
print(mytable.newkey,mymetatable.newkey)
--輸出:nil v2 :普通表中不含“newkey”,會調用元方法mytable.k1="newV"
print(mytable.k1,mymetatable.k1)
--輸出:newV nil :普通表中含有K1,會進行賦值,不再調用元方法
2.元方法調用函數
mytable=setmetatable({k1="v1"},{__newindex=function(mytable,k,v)--重寫元方法rawset(mytable,k,"\""..v.."\"")--rawset繞過原表機制,直接向原表中插入新鍵值對end})mytable.k1="new v1";mytable.k2=3;--由于初始表中不k2,則會向元表中查詢元方法print(mytable.k1,mytable.k2);--輸出:v1 "3"
3.合并元表
function table_max(t)--獲取原表最大鍵--用“#”或者table.getn時,若鍵不連續,只會獲取第一段的最大值maxk=0;for k,v in pairs(t) doif type(k)=="number" and k>maxk thenmaxk=kendendreturn maxk
end--實現兩表合并
mytable=setmetatable({1,2,3},{__add=function(mytable,newtable)local mytable_maxk=table_max(mytable)for i=1,table_max(newtable) --遍歷newtabletable.insert(mytable,mytable_maxk+i,newtable[i])--將newtable中的數據插入到mytable中endreturn mytableend})newtable={4,5,6}
mytable=mytable+newtablefor k,v in pairs(mytable) doprint(k.."--"..v)
end
元方法 | 運算操作 |
---|---|
__add | “+” |
__sub | “-” |
__mul | “*” |
__div | “/” |
__mod | “%” |
__unm | “-” |
__concat | “…” |
__eq | “==” |
__it | “<” |
__le | “<=” |
注:“__"兩個下劃線,__sub對應二元減(兩個參數);__unm對應一元減(只有一個參數)。