当前位置: 代码迷 >> 综合 >> lua 元表
  详细解决方案

lua 元表

热度:23   发布时间:2024-01-25 23:29:48.0

一、元表概述

通常,Lua中的每个值都有一套预定义操作集合,比如数字可以相加,字符串可以连接,表中可以插入键值对等;但是我们无法对两个table相加,无法对函数进行比较等;

元表的出现可以解决以上问题:我们可以通过元表来修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定的操作;

Lua中每个值都有一个元表,table和userdata可以有各自独立的元表,其它类型的值则共享其类型所属的单一元表;在Lua代码中,只能设置table的元表,其它类型的值的元表需要通过C代码来完成;

元表就是,如果一个tableB 调用setmetatable方法设置另外一个tableA作为它的元表,那么当你操作tableB进行一些操作如设置键值,查找键值,table间使用运算符号、或者直接传个参数调用等操作时,结果就会变得不一样或者原本不可行操作的现在可行了。而tableA之所以能作为元表,是因为里面包含了特殊的键(也就是元方法)代表着特殊的含义,代码在运行时会做特殊的处理。

元表的作用就在于它允许我们通过元表来改变表的行为;元方法类似于操作符重载;

二、表相关的元方法

1.__index元方法

__index用于对表访问,相当于属性的get方法;

Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:

  • 1.在表中查找,如果找到,返回该元素,找不到则继续
  • 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
  • 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,会把table和键作为参数传递给这个函数,然后返回该函数的返回值。
other={k2="value2"}
local mytable=setmetatable({k1="value1"},{__index=other})
--print(getmetatable(mytable))
--print(mytable.k1 .. mytable.k2)other={__index=function(table,key2)if key2=="k2" thenreturn 'this is k2'elsereturn nilend
end
}
mytable=setmetatable(mytable,other)print(mytable.k1 .. mytable.k2)

2.__newindex元方法

__newindex用于对表更新,相当于属性的set方法;

__newindex的规则:

  • 首先根据字段查找table,如果检查到table有该字段,则更新该字段;然后检查是否有元表,且元表是否有__newindex方法,如果没有,则给table中添加该字段;如果有_newindex元方法,继续以下操作;
  • 如果__newindex是一个函数,则在给table不存在的字段赋值时,会调用这个函数。
  • 如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值。

应用:

  • __newindex是一个function时,可用来控制一个表中不存在的字段的赋值行为,例如当不希望子类覆盖父类方法或者修改父类成员时,可以对子类__newindex进行修改
  • 保护__index里面的元素不被修改,让其只读

三、参考

OpenResty-元表

菜鸟教程-元表

  相关解决方案