Lua元表Metatable

2018-06-27  本文已影响0人  凉拌姨妈好吃

1. 元表的含义

元表是带有索引集合的表,它可以改变被附加的表的行为

2. 算术类的元方法

下面是我们为我们table赋值,这个table是一个普通表,它的value是一个有参函数


1

我们定义一个元表mt

local mt={}

然后重新修改一下上面的table集合的初始化函数,将元表加入集合中:setmetatable


集合的初始化

我们为元表设置元方法,此时下面的Set.union就是元方法,它用于描述如何完成加法的__add字段
当我们在进行表a+b的时候:

  1. 检查第一个值是否有元表,并且表中有add字段,有就以这个字段的值为元方法,反之第二个值有元表就用它为元方法,如果都没有,就抛出错误
  2. 如果有__add,就取得它的值,此时这个值就是我们的元方法,里面编写了add函数的实现
mt.__add = Set.union

在元表中,每种算术操作符都有对应的字段名。

3. __index元方法

3.1 它的作用

当我们访问table的一个不存在的字段时,如果没有__index这个元方法,那么就会返回nil,如果有这个元方法,就会由这个元方法来提供最终的结果。
上面这段是什么意思呢?我们下面通过对象多态性的实现来理解这个概念

如果想让__index的重写失效,我们可以使用rawget

print(rawget(s2.gio()))-----返回nil,因为绕过__index,在s2中找不到gio,所以返回nil

3. __newindex元方法

当对一个table中不存在的索引赋值时,解释器就会去查找__newindex元方法,如果有这个元方法,解释器就调用它,而不是进行赋值nil。如果这个元方法是一个table,解释器就在这个table里进行赋值,而不是对原来的table

    local smartMan = {
        name = "none",
    }
   
    local other = {
        name = "大家好,我是很无辜的table"
    }
   
    local t1 = {};
   
    local mt = {
        __index = smartMan,
        __newindex = other
    }
   
    setmetatable(t1, mt);
     
    print("other的名字,赋值前:" .. other.name);
    t1.name = "小偷";
    print("other的名字,赋值后:" .. other.name);
    print("t1的名字:" .. t1.name);

[LUA-print] other的名字,赋值前:大家好,我是很无辜的table
[LUA-print] other的名字,赋值后:小偷
[LUA-print] t1的名字:none

因为我们给元表设置了:__newindex这个元方法,所以我们在给t1.name赋值的时候,因为t1没有这个属性,所以我们就去__newindex对应的other这个table下进行赋值,所以此时other就被赋值为小偷

4. 跟踪table的访问

使用了上面的__index 和__newindex,我们可以发现,这些都是在table里没有所需访问的index时才发挥作用的,所以只有当一个table为空的时候,才能捕获到所有对它的访问。所以当我们需要监视一个table的时候,可以创一个table代理,用来跟踪table的所有访问。

跟踪访问
上一篇下一篇

猜你喜欢

热点阅读