Lua中的元方法__newindex详解

好吧,我写文章的进度已经赶不上看书的进度了,简单的几段文字就够我唠叨一篇文章了。

今天继续来说说元方法,与__index有点相似的__newindex元方法。

1.查询与更新

上一篇文章我们介绍了__index元方法,总结来说,__index元方法是用于处理调用table中不存在的字段。

注意,【调用】这个词,只是调用,而不是赋值。
 
如果,我们要对table中某个不存在的字段赋值呢?(小若:就,直接赋值啊!)

没错,我们直接就能赋值了,不会报错的。

问题是,如果我想监控这个操作呢?如果有人想对table不存在的字段进行赋值的时候,我想进行一些额外的处理呢?

这时候就要用到__newindex。
 
大家要记住这句话:__index用于查询,__newindex用于更新。

等会不要混乱了, 初次接触的话,有可能会混乱。

2.看看普通的赋值情况

我们先来看看正常情况下的赋值,如代码:

代码如下:

local smartMan = {
        name = "none",
        money = 9000000,
      
        sayHello = function()
            print("大家好,我是聪明的豪。");
        end
    }
  
    local t1 = {};
  
    local mt = {
        __index = smartMan,
    }
  
    setmetatable(t1, mt);
  
    t1.sayHello = function()
        print("en");
    end;
  
    t1.sayHello();

这是上一篇用过的例子,一个模仿继承结构的例子。
来分析一下,mt作为t1的元表,设置__index为smartMan。
于是,当我们调用t1中不存在的字段时,就会自动去smartMan中查找。
比如我们调用了t1.sayHello(),自然能找到对应的函数。
 
先来看看输出结果:

代码如下:

[LUA-print] en

我们调用t1的sayHello字段,t1并不存在这个字段(虽然可以通过__index的方式来找到smartMan的sayHello字段)。

但这不影响,给这个字段赋值,然后再调用t1.sayHello(),发现是成功的。

这和我们以往的做法一样,对table做正常的赋值操作,不管table本身是否存在这个字段。

3.监控赋值

好了,普通情况我们已经试过了,如果我们想监控table的赋值操作呢?
对于不存在的字段,我们不需要被赋值呢?想要制作一个只读的table呢?
 
如果你有这些想法,那么欢迎拨打屏幕下方的号码,前10位打进的还赠送价值..(小若:停!)
那么,如果你有这些想法,请看看下面的代码:

代码如下:

local smartMan = {
        name = "none",
        money = 9000000,
      
        sayHello = function()
            print("大家好,我是聪明的豪。");
        end
    }
  
    local t1 = {};
  
    local mt = {
        __index = smartMan,
        __newindex = function(table, key, value)
            print(key .. "字段是不存在的,不要试图给它赋值!");
        end
    }
  
    setmetatable(t1, mt);
  
    t1.sayHello = function()
        print("en");
    end;
    t1.sayHello();

留意mt元表,我们给它加了一个__newindex。
运行代码,输出结果如下:

代码如下:

[LUA-print] sayHello字段是不存在的,不要试图给它赋值!
[LUA-print] 大家好,我是聪明的豪。

很显然,sayHello字段赋值失败,因为给sayHello字段赋值的时候,调用了__newindex元方法,代替了赋值操作。

(小若:为什么?sayHello字段不是存在的么?为什么会说不存在呢?)
 
这里有一个地方要注意的,t1中确实是不存在sayHello字段的,它只是因为有元表存在,而元表里的__index元方法的值是smartMan这个table。

从而,可以在t1找不到sayHello字段的时候,去smartMan中寻找。

但,实际上,t1确实是不存在sayHello字段的,不知道大家能绕明白不?
 
因此,当试图给t1的sayHello字段赋值时,Lua判定sayHello字段是不存在的,所以会去调用元表里的__newindex元方法。

__newindex元方法被调用的时候会传入3个参数:table本身、字段名、想要赋予的值。

4.隔山打牛,通过给一个table给另一个table的字段赋值

和__index一样,__newindex元方法也可以赋予一个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);

这次的代码和刚刚差不多,但是我们新加了一个other的table,然后把other作为__newindex的值。

于是,当给t1的name字段赋值时,就会发生一些奇怪的事情…

先来看看输出结果:

代码如下:

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

当给t1的name字段赋值后,other的name字段反而被赋值了,而t1的name字段仍然没有发生变化。

(实际上t1的name字段还是不存在的,它只是通过__index找到了smartMan的name字段,这个就不唠叨了。)

于是,我们给t1的name赋值的时候,实际上是给other的name赋值了。

好吧,可怜的other。

5.总结规则

这就是__newindex的规则:

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

6.结束

好了,关于元表和元方法的基础内容基本上告一段落了,接下来还有一篇关于元表和元方法的文章,也是一些比较零散的知识点。

之后,还会提到元表和元方法的,因为它们实在是太重要了。

(0)

相关推荐

  • Lua中强大的元方法__index详解

    今天要来介绍比较好玩的内容--__index元方法 1.我是备胎,记得回头看看 咳咳,相信每一位女生都拥有或者不知不觉中拥有了一些备胎,啊,当然,又或许是成为过别人的备胎. 没有备胎的人,就不是完整的人生.(小若:停!)   我们来想象一下,如果对一个table进行取值操作,但是table根本就没有这个值呢? 比如: 复制代码 代码如下: local t = {         name = "hehe",     }     print(t.money); 输出结果当然是:nil t

  • Lua中__index和__newindex之间的沉默与合作

    因为不想在一篇文章里挤太多知识点,所以,有些小知识点就集合到这样的文章里吧~ 1.沉默技能--拒绝__index和__newindex效果 虽然__index和__newindex是很好用的功能,但是,有时候我们又希望很纯粹地去调用table或者给table赋值. 那,这时候怎么办?给table重新设置一个元表?不,这个做法很糟糕~ 于是,体贴的Lua又给我们提供了这样的调用方式,如下代码: 复制代码 代码如下: local smartMan = {         name = "none&q

  • Lua中的元方法__newindex详解

    好吧,我写文章的进度已经赶不上看书的进度了,简单的几段文字就够我唠叨一篇文章了. 今天继续来说说元方法,与__index有点相似的__newindex元方法. 1.查询与更新 上一篇文章我们介绍了__index元方法,总结来说,__index元方法是用于处理调用table中不存在的字段. 注意,[调用]这个词,只是调用,而不是赋值.   如果,我们要对table中某个不存在的字段赋值呢?(小若:就,直接赋值啊!) 没错,我们直接就能赋值了,不会报错的. 问题是,如果我想监控这个操作呢?如果有人想

  • Kotlin 语言中调用 JavaScript 方法实例详解

    Kotlin 语言中调用 JavaScript 方法实例详解 Kotlin 已被设计为能够与 Java 平台轻松互操作.它将 Java 类视为 Kotlin 类,并且 Java 也将 Kotlin 类视为 Java 类.但是,JavaScript 是一种动态类型语言,这意味着它不会在编译期检查类型.你可以通过动态类型在 Kotlin 中自由地与 JavaScript 交流,但是如果你想要 Kotlin 类型系统的全部威力 ,你可以为 JavaScript 库创建 Kotlin 头文件. 内联 J

  • jQuery中ajax - post() 方法实例详解

    在jquery中的ajax有二个数据发送模式,一种是get,另一种是post(). jQuery Ajax 参考手册 实例 请求 test.php 网页,忽略返回值: $.post("test.php"); TIY 实例 通过 AJAX POST 请求改变 div 元素的文本: $("input").keyup(function(){ txt=$("input").val(); $.post("demo_ajax_gethint.asp

  • jQuery中ajax - get() 方法实例详解

    在jquery中使用get,post和ajax方法给服务器端传递数据,在上篇文章给大家分享了jquery中ajax-post()方法实例,下面通过本文继续学习jQuery中ajax - get() 方法,具体介绍请看下文. jQuery Ajax 参考手册 实例 使用 AJAX 的 GET 请求来改变 div 元素的文本: $("button").click(function(){ $.get("demo_ajax_load.txt", function(resul

  • jsp 中HttpClient中的POST方法实例详解

    jsp 中HttpClient中的POST方法实例详解 POST方法用来向目的服务器发出请求,要求它接受被附在请求后的实体,并把它当作请求队列(Request-Line)中请求URI所指定资源的附加新子项.POST被设计成用统一的方法实现下列功能: 对现有资源的注释 向电子公告栏.新闻组,邮件列表或类似讨论组发送消息 提交数据块,如将表单的结果提交给数据处理过程 通过附加操作来扩展数据库 调用HttpClient中的PostMethod与GetMethod类似,除了设置PostMethod的实例

  • JavaScript 中调用 Kotlin 方法实例详解

    JavaScript 中调用 Kotlin 方法实例详解 Kotlin 编译器生成正常的 JavaScript 类,可以在 JavaScript 代码中自由地使用的函数和属性 .不过,你应该记住一些微妙的事情. 用独立的 JavaScript 隔离声明 为了防止损坏全局对象,Kotlin 创建一个包含当前模块中所有 Kotlin 声明的对象 .所以如果你把模块命名为 myModule,那么所有的声明都可以通过 myModule 对象在 JavaScript 中可用.例如: fun foo() =

  • JavaScript中的splice方法用法详解

    JavaScript中的splice主要用来对js中的数组进行操作,包括删除,添加,替换等. 注意:这种方法会改变原始数组!. 1.删除-用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数) 2.插入-向数组指定位置插入任意项元素.三个参数,第一个参数(插入位置),第二个参数(0),第三个参数(插入的项) 3.替换-向数组指定位置插入任意项元素,同时删除任意数量的项,三个参数.第一个参数(起始位置),第二个参数(删除的项数),第三个参数(插入任意数量的项) 示例:

  • Lua中的元表(metatable)、元方法(metamethod)详解

    终于到了在实际中经常要用到的内容了--元表与元方法. 在第一次看见这两样东西的时候,可能会觉得它很深奥,但其实很好理解,虽然实际上它可能真的很深奥.(小若:停!滚粗.) 1.知道为什么1 + 1 = 2吗? 为什么在Lua中,1+1会等于2呢?(小若:难道除了Lua,其他地方就不等于2了?) 为什么数字和数字相加是合法的,为什么table和table相加就会报错?大家有想过这些问题吗?   没错,规则,这一切都只是规则而已,Lua规定了数字之间可以进行加减乘除,而table之间则不可以. 这是因

  • Lua中关于元方法的一些知识点小结

    本篇要介绍的东西比较零散,都是一些小知识点,所以就放在一起了. 1.两个具有不同元表的值进行算术操作(比如加法) 之前举例的时候,两个table相加,这两个table都是具有相同的元表的,所以没有任何问题. 那么,如果两个table或者两个进行相加操作的值,具有不同的元表呢? 对于这种情况,Lua是这样处理: a.如果第一个值有元表,就以这个元表为准 b.否则,如果第二个值有元表,就用第二个值的元表 c.如果两个值都没有元表,或者没有对于的元方法,那么,就会报错 2.关系类的元方法 除了加法减法

随机推荐