1. 元表的含义
元表是带有索引集合的表,它可以改变被附加的表的行为
2. 算术类的元方法
下面是我们为我们table赋值,这个table是一个普通表,它的value是一个有参函数
1
我们定义一个元表mt
local mt={}
然后重新修改一下上面的table集合的初始化函数,将元表加入集合中:setmetatable
集合的初始化
我们为元表设置元方法,此时下面的Set.union就是元方法,它用于描述如何完成加法的__add字段
当我们在进行表a+b的时候:
- 检查第一个值是否有元表,并且表中有add字段,有就以这个字段的值为元方法,反之第二个值有元表就用它为元方法,如果都没有,就抛出错误
- 如果有__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的所有访问。
跟踪访问