Lua元方法__newindex

上篇博客我们讲了__index用于查询,这一节我们讲_newindex , _newindex 元方法用来对表更新,__index则用来对表访问 。
当你给表的一个缺少的索引赋值,解释器就会查找__newindex 元方法:如果存在则调用这个函数而不进行赋值操作

我们先来看下简单的赋值操作

father = {
    	house=1,
    	sayHello = function()
            print("大家好,我是father.");
        end
    }
    father.__index = father
    son = {
    	car=1
    }
    son.sayHello = function()
            print("大家好,我是son.");
        end
    setmetatable(son, father) --把son的metatable设置为father

    print(son.sayHello())

输出值为:大家好,我是son.

我们调用son.sayHello,虽然son可以通过元表找到这个字段,但是它本身不存在这个字段,但这并影响我们给他赋值,最后调用sayHello成功显示

如果我们不想给son中不存在的字段赋值的时候如何检测呢,这时候元方法__newindex就派上用场了,示例代码如下:

    local father = {
    	house=1,
    	sayHello = function()
            print("大家好,我是father.");
        end
    }
    
    local temp ={
        
        __index = father,
        __newindex = function(table, key)
            print(key .. "字段是不存在的,不允许给它赋值!");
        end
    }
    
    son = {
    	car=1
    }
    setmetatable(son, temp) --把son的metatable设置为father
    son.sayHello = function()
            print("大家好,我是son.");
        end
    
    son.sayHello()

当我们给sayHello赋值的时候调用了__newindex元方法,代替了赋值操作,表son中确实不存在sayHello字段,只是因为它的元表中有而已,因此当我们给sayHello赋值时,lua判断sayHello不存在回去调用元表里的__newindex方法,当然了,这里的__newindex赋值不一定时function,也可以时另外一个表比如

    local pt = {
        house = 2
    }
    local father = {
    	house=0,
    	sayHello = function()
            print("大家好,我是father.");
        end
    }
    
    local temp ={
        
        __index = father,
        __newindex = pt
    }
    
    son = {
    	car=1
    }
    setmetatable(son, temp) --把son的metatable设置为father
    print("赋值前:" .. pt.house);
    son.house = 10;
    print("赋值后:" .. pt.house);
    print("son.house:" .. son.house);

输出如下:

赋值前:2
赋值后:10
son.house:0

可以看到,当我们给son.house赋值时实际上是给pt.house赋值了。son.house本身不存在,取的是father的house值

这里再引用下菜鸟教程中的例子加深理解下

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)

 

输出:

value1
nil    新值2
新值1    nil

当我们给mytable.newkey赋值时,会直接将值赋给mymetatable 的newkey字段,mytable本身没有这个字段

当我们给mytable.key1赋值时会直接覆盖已有值而不调用元方法 __newindex,此时mymetatable为nil

最后给个例子加深下理解

local pt = {
        house = 2
    }
    local father = {
    	sayHello = function()
            print("大家好,我是father.");
        end
    }
    
    local temp ={
        
        __index = father,
        __newindex  = function()
            end
    }
    
    son = {
    	car=1
    }
    setmetatable(son, temp) 
    son.house = 10;
    print("son.house:" .. son.house);
至此我们很容易判断出son因为没有house字段会报错,如果把temp中__newindex字段赋值去掉,则能正常打印出10

简单总结下:

如果__newindex是一个函数,则在给table不存在的字段赋值时,会调用这个函数。
如果__newindex是一个table,则在给table不存在的字段赋值时,会直接给__newindex的table赋值。

over!

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值