在 lua table 中我們可以訪問對應的key來得到value值,但是卻無法對兩個 table 進行操作。因此 lua 提供了元表(metatable),允許我們改變table的行為,lua中的每個值都可以用乙個metatable來表示,每個行為則關聯了對應的元方法。
元表的處理有兩個很重要的函式:
setmetatable(table,metatable): 對指定 table 設定元表(metatable),如果元表(metatable)中存在 __metatable 鍵值,setmetatable 會失敗。
getmetatable(table): 返回物件的元表(metatable)。
使用getmetatable來獲取乙個table或userdata型別變數的元表,當建立新的table變數時,使用getmetatable去獲取元表,將返回nil;同樣的,我們也可以通過使用setmetatable去設定乙個table或userdata型別變數的元表。
注:lua在建立新的table時不會建立元表,lua**中只能設定table的元表。
例1:
local t=
print(getmetatable(t))
輸出結果:
nil
例2:
local t=
print(getmetatable(t))
local t1={}
setmetatable(t,t1)
assert(getmetatable(t)==t1)
print(getmetatable("hello world"))
print(getmetatable(10))
輸出結果:
nil
table: 0xfb9e40
nil
如何對指定的表設定元表例項:
mytable = {} -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 設為 mytable 的元表
以上**也可以直接寫成一行:
mytable = setmetatable({},{})
返回物件元表:
getmetatable(mytable) -- 返回mymetatable
當我們訪問乙個table中不存在的字段時,預設情況下,得到的結果是nil,但是這種情況很容易被改變,lua是按照以下步驟決定是返回nil還是其他值:
1.當訪問乙個table的字段時,如果table有這個字段,則直接返回對應的值。
2.通過鍵來訪問 table 的時候,如果這個鍵沒有值,那麼lua就會尋找該table的metatable(假定有metatable)中的__index 鍵。如果__index包含乙個**,lua會在**中查詢相應的鍵。如果__index包含乙個函式的話,lua就會呼叫那個函式,table和鍵會作為引數傳遞給函式。
3.呼叫__index 元方法檢視表中元素是否存在,如果不存在,返回結果為 nil;如果存在則由 __index 返回結果。
注:__index元方法不必一定是乙個函式,也可以是乙個table.
例1:
mytable = setmetatable(, )
print(mytable.key1,mytable.key2)
輸出結果:
value1 metatablevalue
例項解析:
1.mytable 表賦值為 。
2.mytable 設定了元表,元方法為 __index。
3.在mytable表中查詢 key1,如果找到,返回該元素,找不到則繼續。
4.在mytable表中查詢 key2,如果找到,返回 metatablevalue,找不到則繼續。
5.判斷元表有沒有__index方法,如果__index方法是乙個函式,則呼叫該函式。
6.元方法中檢視是否傳入 "key2" 鍵的引數(mytable.key2已設定),如果傳入 "key2" 引數返回 "metatablevalue",否則返回 mytable 對應的鍵值。
以上**也可簡單寫成:
mytable = setmetatable(, })
print(mytable.key1,mytable.key2)
__newindex元方法與__index類似,__newindex 元方法用於更新table中的資料,__index用於查詢table中的資料。
1.當你給表乙個缺少的索引賦值時,lua直譯器會先判斷這個table是否有元表
2.如果沒有元表,則直接新增這個索引,進行對應的賦值。如果有元表,則查詢元表中是否有__newindex 元方法。
3.如果有這個__newindex元方法,lua直譯器執行呼叫這個函式而不進行賦值操作。
4.如果這個__newindex對應的不是乙個函式,而是乙個table時,lua直譯器就在這個table中執行賦值,而不是對原來的table執行操作。
例1:
mymetatable = {}
mytable = setmetatable(, )
print(mytable.key1)
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)
輸出結果:
value1
nil 新值2
新值1 nil
例項解析:
1.表設定了元方法 __newindex
2.在對新索引鍵(newkey)賦值時(mytable.newkey = "新值2"),會呼叫元方法,而不進行賦值。
3.對已存在的索引鍵(key1),會進行賦值,而不呼叫元方法 __newindex。
例2:
local tb1={}
local tb2={}
tb1.__newindex=tb2
tb2.__newindex=tb1
setmetatable(tb1,tb2)
setmetatable(tb2,tb1)
tb1.x=5
輸出結果:
/usr/local/lua-5.3.5/lua53: script.lua:10: '__newindex' chain too long; possible loop
stack traceback:
script.lua:10: in main chunk
[c]: in ?
exited with error status 1
Lua 基礎之元表
print getmetatable hello 003e7050 print getmetatable lua 003e7050 print getmetatable 12 nil print getmetatable nil t print getmetatable t nil setmetat...
Lua語言學習之元表與元方法
元表與元方法 在學習table的時候已經提到這兩個概念。其實,可以把這兩個概念和c 中的運算子過載進行比較,在功能上確有相似性。例如,c 中自定義的型別不能進行數 算,但是我們可以過載運算子就可以 進行數 算操作。lua中就是用元表和元方法來實現這個功能的。lua中的 table 都可以有元表,我們...
Lua基礎之元表(metatable)
lua中的元表允許我們通過乙個tablea特殊的鍵值自定義另乙個tableb的行為,這些特殊的鍵值稱為元方法,tablea則稱為tableb的元表。函式 描述 index 呼叫乙個索引 newindex 給乙個索引賦值 add 運算子 sub 運算子 mul 運算子 div 運算子 mod 運算子 ...