Lua——3.元表Metatable
阿新 • • 發佈:2018-02-27
gpo imageview todo 支持 img tex ont ive 三個參數
lua中的__index元方法
__index指向表時:
__index指向一個方法時
__newindex元方法
lua的metatable也是一個普通的表,lua提供metatable的功能,主要有一下幾種作用:
- 控制對 table 的訪問
- 為 Lua 函數庫提供支持
重載算數運算符和關系運算符的行為
1.使用metatable控制對table的訪問
當查詢table的某個鍵的時候,如果該table的這個鍵沒有值,那麽Lua就會尋找該table的metatable中的__index元方法:如果__index指向一個table,Lua會在此table中查找相應的鍵, 並且,__index也可以指向一個方法
當對table的某個鍵進行賦值時,如果該table存在該字段則為之賦值,若沒有,那麽Lua就會尋找該table的metatable中的__newindex元方法:如果__newindex指向一個table時,Lua會對這個table進行賦值操作,如果__newindex指向一個方法,Lua則會調用該方法
lua中的__index元方法
如果__index包含一個表格,Lua會在此表格中查找相應的鍵。
並且,__index可以指向一個表也可以指向一個方法
__index指向表時:
之前我們需要知道,當我們在一個表中查找一個元素時
首先在該表中查找,有則返回對應值,無則查看該表是否有元表metatable
若無元表則返回nil
有元表時,lua並不是在其元表中查找,而是在其元表的__index域中查找
因此:僅使用setmetatable()方法設置元表,並不能取得對應元表中的元素
BaseClass = {theKey1 = "the string value1"} --[[ DerivedClass = {} setmetatable(DerivedClass,BaseClass) ]]-- --註釋的兩句可簡寫為: DerivedClass = setmetatable({},BaseClass) res = DerivedClass.theKey1 print(res)
設置對應元表的__index鍵之後:
BaseClass = {theKey1 = "the string value1"}
BaseClass.__index = BaseClass
DerivedClass = setmetatable({},BaseClass)
res = DerivedClass.theKey1
print(res)
也可以換一種簡寫方法:
BaseClass = {theKey1 = "the string value1"} DerivedClass = setmetatable({},{__index = BaseClass}) --即直接設 AnonymousTable = {__index = BaseClass} 為DerivedClass的元表,查找時可直接在AnonymousTable中的__index域對應的表BaseClass中查找 res = DerivedClass.theKey1 print(res)
所以,lua中的繼承可以表示為:
local Car = {}
Car.__index = Car
function Car:new(o)
o = o or {}
setmetatable(o,Car)
return o
end
function Car:run()
print("Car‘s run func.")
end
--直接調用“父類”中的run方法
Car.run()
local FordCar = Car:new()
--子類調用“父類”中的run方法
FordCar.run()
--重寫fordCar中的run方法
function FordCar:run()
print("FordCar‘s run func.")
end
--重寫之後調用
FordCar.run()
__index指向一個方法時
__index指向一個方法時,在我們訪問該 table 的不存在的域時,Lua 會嘗試調用 __index 元方法metamethod (__index metamethod 可以接受兩個參數 table 和 key)
local t1 = {}
t1.__index = function(table,key)
print("call the __index metamethod")
print("table"..tostring(table))
print("key"..key)
return key.." from the __index"
end
--set t1 as t2‘s metatable
local t2 = setmetatable({},t1)
--pass the table and the key to __indexmetamethod
local res = t2.key1
print("the result is :"..res)
print("------------------")
res = t2.key2
print("the result is :"..res)
__newindex元方法
如果對 table 的一個不存在的域賦值時,Lua 將檢查 __newindex metamethod:
1.如果 __newindex 為函數,Lua 將調用函數而不是進行賦值(如果 __newindex 為一個函數,它可以接受三個參數 table key value。如果希望忽略 __newindex 方法對 table 的域進行賦值,可以調用 rawset(t, k, v))
2.如果 __newindex 為一個 table,Lua 將對此 table 進行賦值
--file:newindex.lua
local mt = {
key1 = "key1‘s value"
}
local other = {
key1 = "the old value"
}
mt.__index = mt
--[[
mt.__newindex = function()
print "Can not set value"
end
--]]
mt.__newindex = other
local t = setmetatable({},mt)
t.key1 = "the new value from the table t."
print(t.key1)
--對__newindex指向的table中的key1進行更新操作,但是table t 中仍然沒有鍵key1,進行t.key1的查詢時,查詢的仍然是__index中對應的鍵key1的值
print(other.key1)
2. 為 Lua 函數庫提供支持
Lua 庫可以定義和使用 metamethod 來完成一些特定的操作
一個典型的例子是 Lua Base 庫中 __tostring 函數,print 函數會調用此函數進行輸出,調用print時,會檢查並調用 __tostring metamethod
--file:tablelib.lua
local mt = {}
mt.__tostring = function(t)
return ‘{‘..table.concat(t,‘,‘)..‘}‘
end
local t = {1,2,3}
print(t)
print("-----------------")
setmetatable(t,mt)
print(t)
3. 重載算數運算符和關系運算符的行為
//TODO
Lua——3.元表Metatable