[Lua系列]元表介绍

76 阅读2分钟

为什么要用元表

目的:元表拓展了普通表的行为。可以更方便进行普通表的操作

  • 定义两个表a ={},b = {},想对a、b进行加法计算,通过元表操作会更方便(也可通过for循环计算)。

如何设置元表

--1. 设置元表  setmetatable(mytable,mymetatable)  ----
mytable = {"orange","banana"}   --定义普通表
mymetatable = {}   --定义元表
setmetatable(mytable,mymetatable)     -- 把 mymetatable 设为 mytable 的元表
setmetatable(mytable,mymetatable)[1]   --返回mytable的第一个元素“banana”

mytable = setmetatable({"orange","banana"},mymetatable)  --也可以直接这样定义

--2. 返回元表  getmetatable(mytable) -----
getmetatable(mytable)                 -- 返回 它的mymetatable元表

__index 元方法(最常用的键)

*注意,所有的下划线都是两个

作用:当普通表没有该元素时

  • 是否有元表(没有:返回nil)
    • 判断元表有没有 __index 方法(没有:返回nil)
      • __index 方法为 nil:则返回 nil;
      • __index 方法是一个表:则重复 1、2、3(表中有元素,则返回;没有,则返回nil);
      • __index 方法是一个函数:则返回该函数的返回值。

举例

---__inde方法是一个表 ---
> other = { foo = 3 }  
> t = setmetatable({}, { __index = other })  
> t.foo   // 表中有该元素,返回
3  
> t.bar  // 表中无该元素,返回nil
nil

---__inde方法是一个函数 ---
mytable = setmetatable({key1 = "value1"}, 
{  
  __index = function(mytable, key)  
    if key == "key2" then  
      return "metatablevalue"  
    else  
      return nil  
    end  
  end  
})  
  
print(mytable.key1) // 有key1,输出value1 
print(mytable.key2) // 普通表没有key2,return "metatablevalue" ,输出metatablevalue


__newindex

作用:当修改的是新的索引时起作用(给表添加新的键值对)

当该索引在普通表里时,按照普通表的走;当该索引不在普通表里时,按照__newindex走

mytable = {"orange","banana"}
mymetatable = 
{
  __newindex = function(tab,key,value)
      print("修改的key:"..key.."把key的值修改为:"..value)
      rawset(mytable, key, "\""..value.."\"") -- 将元素加入表里.注意"\""
      --如果不加这个,原普通表还是没改变
      --如果换成mytable[key] = value,会一直陷入死循环
  end
}

mytable = setmetatable(mytable,mymetatable)

mytable[1] = "apple" -- 输出结果   apple
mytable[4] = "grape" -- 输出结果  修改的key:4 把key的值修改为:grape



操作符

__addindex 实现连接两个表

--要合并的两个表
mytable = {1,2,3}
secondtable = {4,5,6}

--定义元表的方法
mytable = setmetatable(mytable, {
  __add = function(mytable, newtable)
  ---找到mytable的最大长度
    local mn = 0
    for k, v in pairs(mytable) do
        if mn < k then
            mn = k
        end
    end
  ---一个个放入newtable的值
    for k, v in pairs(newtable) do
      mn = mn + 1
      table.insert(mytable, mn, v)
    end
    return mytable
  end
})


mytable = mytable + secondtable
        for k,v in ipairs(mytable) do
print(k,v)
end

其他操作符类似

_add对应的运算符 '+'.
__sub对应的运算符 '-'.
__mul对应的运算符 '*'.
__div对应的运算符 '/'.
__mod对应的运算符 '%'.
__unm对应的运算符 '-'.
__concat对应的运算符 '..'.
__eq对应的运算符 '=='.
__lt对应的运算符 '<'.
__le对应的运算符 '<='.