元表(metatable
)是一個表,它是使用鍵集和相關元方法來修改附加到的表的行為。 這些元方法是強大的Lua功能,可實現如下功能 -
- 在表上更改/添加功能到操作符。
- 使用元表中的
__index
在表中沒有鍵時查找元表。
在處理元表時有兩種重要的方法,包括 -
setmetatable(table,metatable)
- 此方法用於為表設置元表。getmetatable(table)
- 此方法用於獲取表的元表。
首先來看看如何將一個表設置為另一個表的元表。 如下所示 -
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
上面的代碼可以用一行表示,如下所示 -
mytable = setmetatable({},{})
_index
下表顯示了元表在表中不可用時查找元表的示例。
mytable = setmetatable({key1 = "value1"}, {
__index = function(mytable, key)
if key == "key2" then
return "metatablevalue"
else
return mytable[key]
end
end
})
print(mytable.key1,mytable.key2)
當運行上面的程式時,將得到以下輸出結果 -
value1 metatablevalue
下麵來逐步看看上面例子中發生的事情。
- 這裏表
mytable
是{key1 = "value1"}
。 - 元表設置為
mytable
,其中包含__index
的函數,它稱為元方法。 - 元方法執行查找索引
key2
,如果找到它,則返回metatablevalue
,否則返回相應索引的mytable
值。
上述程式的簡化版本,如下所示 -
mytable = setmetatable({key1 = "value1"},{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
當將__newindex
添加到metatable
時,如果表中沒有鍵,則新鍵的行為將由元方法定義。 下麵給出了當主表中沒有索引時設置metatable
索引的簡單示例。
mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "new value 1"
print(mytable.key1,mymetatable.newkey1)
運行上述程式時,將獲得以下輸出 -
value1
nil new value 2
new value 1 nil
在上面的程式中看到,如果主表中存在一個鍵,它只會更新它。 當維護中的鍵不可用時,它會將該鍵添加到metatable
中。
使用rawset
函數更新同一個表的另一個示例如下所示 -
mytable = setmetatable({key1 = "value1"}, {
__newindex = function(mytable, key, value)
rawset(mytable, key, "\""..value.."\"")
end
})
mytable.key1 = "new value"
mytable.key2 = 4
print(mytable.key1,mytable.key2)
當運行上面的程式時,將獲得以下輸出。
new value "4"
rawset
設置值而不使用元表的__newindex
。 類似地,有一個rawget
可以在不使用__index
的情況下獲取值。
向表中添加運算符行為
使用+
運算符組合兩個表的簡單示例如下所示 -
mytable = setmetatable({ 1, 2, 3 }, {
__add = function(mytable, newtable)
for i = 1, table.maxn(newtable) do
table.insert(mytable, table.maxn(mytable)+1,newtable[i])
end
return mytable
end
})
secondtable = {4,5,6}
mytable = mytable + secondtable
for k,v in ipairs(mytable) do
print(k,v)
end
當運行上面的程式時,將得到以下輸出 -
1 1
2 2
3 3
4 4
5 5
6 6
__add
鍵包含在元表中以添加運算符 +
的行為。鍵表和相應的操作符如下所示。
編號 | 模式 | 描述 |
---|---|---|
1 | __add |
改變運算符+ 的行為。 |
2 | __sub |
改變運算符- 的行為。 |
3 | __mul |
改變運算符* 的行為。 |
4 | __div |
改變運算符/ 的行為。 |
5 | __mod |
改變運算符% 的行為。 |
6 | __unm |
改變運算符- 的行為。 |
7 | __concat |
改變運算符.. 的行為。 |
8 | __eq |
改變運算符== 的行為。 |
9 | __lt |
改變運算符< 的行為。 |
10 | __le |
改變運算符<= 的行為。 |
__call
使用__call
語句添加方法調用的行為。 一個簡單的示例,它返回主表中的值與傳遞的表的總和。
mytable = setmetatable({10}, {
__call = function(mytable, newtable)
sum = 0
for i = 1, table.maxn(mytable) do
sum = sum + mytable[i]
end
for i = 1, table.maxn(newtable) do
sum = sum + newtable[i]
end
return sum
end
})
newtable = {10,20,30}
print(mytable(newtable))
當運行上面的程式時,將得到以下輸出。
70
__tostring
要更改print
語句的行為,可以使用__tostring
元方法。 一個簡單的例子如下所示。
mytable = setmetatable({ 10, 20, 30 }, {
__tostring = function(mytable)
sum = 0
for k, v in pairs(mytable) do
sum = sum + v
end
return "The sum of values in the table is " .. sum
end
})
print(mytable)
當運行上面的程式時,將得到以下輸出。
The sum of values in the table is 60
如果完全瞭解元表的功能,那麼可以真正執行很多非常複雜的操作。 因此,嘗試使用元表中可用的不同選項的元表更多地工作。