Lua元表

元表(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

如果完全了解元表的功能,那么可以真正执行很多非常复杂的操作。 因此,尝试使用元表中可用的不同选项的元表更多地工作。


上一篇:Lua模块

下一篇:Lua协同程序

关注微信小程序
程序员编程王-随时随地学编程

扫描二维码
程序员编程王

扫一扫关注最新编程教程