表的索引
也許 metatables 最重要的用途是可以改變表的索引。為此,需要考慮兩個操作: 讀取內容並編寫表的內容。請注意,只有在表中不存在相應的鍵時才會觸發這兩個操作。
讀
local meta = {}
-- to change the reading action, we need to set the '__index' method
-- it gets called with the corresponding table and the used key
-- this means that table[key] translates into meta.__index(table, key)
meta.__index = function(object, index)
-- print a warning and return a dummy object
print(string.format("the key '%s' is not present in object '%s'", index, object))
return -1
end
-- create a testobject
local t = {}
-- set the metatable
setmetatable(t, meta)
print(t["foo"]) -- read a non-existent key, prints the message and returns -1
這可用於在讀取不存在的鍵時引發錯誤:
-- raise an error upon reading a non-existent key
meta.__index = function(object, index)
error(string.format("the key '%s' is not present in object '%s'", index, object))
end
寫作
local meta = {}
-- to change the writing action, we need to set the '__newindex' method
-- it gets called with the corresponding table, the used key and the value
-- this means that table[key] = value translates into meta.__newindex(table, key, value)
meta.__newindex = function(object, index, value)
print(string.format("writing the value '%s' to the object '%s' at the key '%s'",
value, object, index))
--object[index] = value -- we can't do this, see below
end
-- create a testobject
local t = { }
-- set the metatable
setmetatable(t, meta)
-- write a key (this triggers the method)
t.foo = 42
你現在可以問自己如何在表中寫入實際值。在這種情況下,它不是。這裡的問題是元方法可以觸發元方法,這會導致不定式迴圈,或更確切地說,堆疊溢位。那我們怎麼解決這個問題呢?解決方案稱為原始表訪問。