元表
元表就是允許我們改變table的行為,你所改變的這個(gè)行為又關(guān)聯(lián)了一個(gè)方法,這個(gè)方法我們稱(chēng)作元方法(系統(tǒng)提供)。
t = {}
print(getmetatable(t)) ?-- nil ?因?yàn)闆](méi)有設(shè)置其元表
m_t = {
__tostring = function (t) ?--設(shè)置元方法
return "aa"
end
}
t1 = setmetatable(t,m_t)
print(t) -- aa
if(t == t1)
then
print("同一張表") --輸出,所以證明其實(shí)t和t1就是同一張表
end
第二種寫(xiě)法
t = setmetatable({},{
__tostring = function (t)
return 111
end
})
print(t)
在lua中創(chuàng)建新的表或者是其他類(lèi)型的時(shí)候,會(huì)為該類(lèi)型提供元表,但是有一個(gè)特例就是字符串
t = 10
print(getmetatable(t)) -- nil
str = "hello"
print(getmetatable(str))--string自帶元表
常用創(chuàng)建元表的方式
setmetatable的兩個(gè)參數(shù),第一個(gè)參數(shù)為改變行為的那張表,第二個(gè)參數(shù)是元表具體的改變行為
T = setmetatable({},{})
__add(t1,t2)? -- 相加行為
__sub(t1,t2)? -- 相減行為
__mul? ? ? ? -- 相乘行為
__div ? -- 相除行為
__len(t1)? ? -- 表的長(zhǎng)度
__index? ? ? -- 索引查詢(xún)
__newindex? ? -- 更新索引
__tostring ? -- 字符串輸出
......
例子
Window = {}
Window.default = {
x = 0,
y = 0,
width = 100,
height = 100,
color = {
r = 255.0,
g = 255.0,
b = 255.0
}
}
--創(chuàng)建一個(gè)元表
Window.mt = {}
--構(gòu)造函數(shù)
function Window.new(obj)
setmetatable(obj,Window.mt)
return obj
end
--__index元方法:查詢(xún)索引
Window.mt.__index = function (tb,key)
print("該方法被調(diào)用")
return Window.default[key]
end
-- Window.mt.__index = Window.default -- 指定表,如果表中沒(méi)有該字段,則去這個(gè)表中的元表中找,找到__index元方法,這個(gè)方法也可以對(duì)
--應(yīng)一張表,只是這樣的話(huà)不能再做攔截的操作了
local win = Window.new({x = 10,y = 20})
print(win.x) --10
print(win.y) --20
print(win.width) -- 該方法被調(diào)用 100
print(win.height) -- 該方法被調(diào)用 100
print(win.x) 由于win變量本身就擁有了x字段,所以直接打印
print(win.width) 由于win變量沒(méi)有該字段,那么就去查找是否擁有元表,如果有,就去元表中查詢(xún)
先看元表中是否有__index元方法對(duì)應(yīng)的方法或者表,
由于存在__index 所以返回default表中width字段
在實(shí)際開(kāi)發(fā)中__index元方法不一定就對(duì)應(yīng)的是函數(shù),也有可能是表
最后總結(jié)一下 Lua 查找一個(gè)元素時(shí)候的規(guī)則
1.在表中查詢(xún),如果找到返回該元素,找不到繼續(xù)
2.判斷該表是否具備元表,如果有繼續(xù),如果沒(méi)有返回nil
3.判斷元表是否具備某種行為,有繼續(xù),沒(méi)有nil