📜  Lua-Metatables

📅  最后修改于: 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

当我们将__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

__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

如果您完全了解元表的功能,那么不使用它就可以执行很多非常复杂的操作。因此,如样本中所述,尝试更多地使用元表中具有不同选项的元表,并创建自己的样本。