Lua 基础教程(十五)元表
hudson 译 原文
Lua的元表
元表是一个表,它包含一组键集合和相关的元方法,使用这些元数据,可以修改其附加的表的行为。这些元方法是强大的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 nil
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添加到元表中时,如果表中没有键,新键的行为将由元方法定义。当索引在主表中不可用时,可在元表中设置索引。如下示例:
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设置值而不使用元表的__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语句用来添加方法调用的行为 。下面是一个简单的示例,返回主表中传递的值之和:
-- Adding behavior of method call is done using __call statement.
-- A simple example that returns the sum of values in the main table with the passed table.
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
要更改打印语句的行为,可以使用__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
如果完全了解元表的功能,就可以执行许多操作,这些操作在不使用元表的情况下非常复杂。 因此,尝试更多地使用元表,以及其可用的不同选项,如示例中解释的那样,并创建自己的样本代码。