📅  最后修改于: 2020-10-16 05:13:20             🧑  作者: Mango
一个元表是一个表,它通过键集和相关的元方法来帮助修改它所附加的表的行为。这些meta方法具有强大的Lua功能,可实现以下功能:
在表上为运算符更改/添加功能。
使用元表中的__index在表中键不可用时查找元表。
处理元表有两种重要的方法,包括-
setmetatable(table,metatable) -此方法用于设置表的元表。
getmetatable(table) -此方法用于获取表的元表。
首先让我们看一下如何将一个表设置为另一个表的元表。如下所示。
mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)
上面的代码可以用单行表示,如下所示。
mytable = setmetatable({},{})
下面显示了一个简单的元表示例,用于在表中不存在时查找元表。
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添加到metatable中时,如果表中没有键,则新键的行为将由meta方法定义。下面给出一个简单的示例,其中当主表中的索引不可用时设置元表的索引。
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
您可以在上面的程序中看到,如果主表中存在键,它只会更新它。当主表中没有键时,它将把该键添加到元表中。
下面显示了另一个使用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设置值而不使用metatable的__newindex。同样,有一些不使用__index即可获取价值的rawget。
一个使用+合并两个表的简单示例运算符如下所示-
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键包含在元表中,以添加运算符+的行为。按键表和相应的运算符如下所示。
Sr.No. | Mode & Description |
---|---|
1 |
__add Changes the behavior of operator ‘+’. |
2 |
__sub Changes the behavior of operator ‘-‘. |
3 |
__mul Changes the behavior of operator ‘*’. |
4 |
__div Changes the behavior of operator ‘/’. |
5 |
__mod Changes the behavior of operator ‘%’. |
6 |
__unm Changes the behavior of operator ‘-‘. |
7 |
__concat Changes the behavior of operator ‘..’. |
8 |
__eq Changes the behavior of operator ‘==’. |
9 |
__lt Changes the behavior of operator ‘<‘. |
10 |
__le Changes the behavior of operator ‘<=’. |
使用__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
要更改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
如果您完全了解元表的功能,那么不使用它就可以执行很多非常复杂的操作。因此,如样本中所述,尝试更多地使用元表中具有不同选项的元表,并创建自己的样本。