扫码一下
查看教程更方便
元表是一个表,它有助于在键集和相关元方法的帮助下修改它所附加的表的行为。 这些元方法是强大的 Lua 功能,可以实现以下功能
__index
查找元表。有两种重要的方法用于处理元表,包括
让我们首先看看如何将一个表设置为另一个表的元表。 如下所示。
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
让我们逐步解释上述示例中发生的情况。
{key1 = "value1"}
。__index
的函数,我们称之为元方法。我们可以拥有上述程序的简化版本,如下所示。
mytable = setmetatable({key1 = "value1"},
{ __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)
__newindex
当我们将 __newindex
添加到 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
我们可以在上面的程序中看到,如果主表中存在一个键,它只是更新它。 当主表中的键不可用时,它会将该键添加到元表中。
另一个使用 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
的情况下获得值。
使用 +
运算符组合两个表的简单示例如下所示
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用 -- 自定义计算表中最大键值函数 table_maxn,即计算表的元素个数 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 两表相加操作 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
元方法在 Lua 调用一个值时调用。以下实例演示了计算表中元素的和:
-- 计算表中最大值,table.maxn在Lua5.2以上版本中已无法使用 -- 自定义计算表中最大键值函数 table_maxn,即计算表的元素个数 function table_maxn(t) local mn = 0 for k, v in pairs(t) do if mn < k then mn = k end end return mn end -- 定义元方法__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
元方法用于修改表的输出行为。以下实例我们自定义了表的输出内容:
mytable = setmetatable({ 10, 20, 30 }, { __tostring = function(mytable) sum = 0 for k, v in pairs(mytable) do sum = sum + v end return "表所有元素的和为 " .. sum end }) print(mytable)
以上实例执行输出结果为:
表所有元素的和为 60
从本文中我们可以知道元表可以很好的简化我们的代码功能,所以了解 Lua 的元表,可以让我们写出更加简单优秀的 Lua 代码。