• 算术运算的元方法 Metamethods


    这一部分我们通过一个简单的例子介绍如何使用 metamethods。假定我们使用 table来描述结合,使用函数来描述集合的并操作,交集操作, like 操作。我们在一个表内定义这些函数,然后使用构造函数创建一个集合:
    在这里插入图片描述
    为了帮助理解程序运行结果,我们也定义了打印函数输出结果:
    在这里插入图片描述
    现在我们想加号运算符(+)执行两个集合的并操作,我们将所有集合共享一个metatable,并且为这个 metatable 添加如何处理相加操作。

    第一步,我们定义一个普通的表,用来作为 metatable。为避免污染命名空间,我们将其放在 set 内部。

    Set.mt = {} -- metatable for sets
    
    • 1

    第二步,修改 set.new 函数,增加一行,创建表的时候同时指定对应的 metatable

    function Set.new (t) -- 2nd version
    local set = {}
    setmetatable(set, Set.mt)
    for _, l in ipairs(t) do set[l] = true end
    return set
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样一来, set.new 创建的所有的集合都有相同的 metatable 了:
    在这里插入图片描述
    下图可知s1和s2的元表相同。
    在这里插入图片描述
    第三步,给 metatable 增加__add 函数。
    在这里插入图片描述
    Lua 试图对两个集合相加时,将调用这个函数,以两个相加的表作为参数。通过 metamethod,我们可以对两个集合进行相加:
    在这里插入图片描述

    同样的我们可以使用相乘运算符来定义集合的交集操作:
    在这里插入图片描述
    结果如下:
    在这里插入图片描述
    对于每一个算术运算符, metatable 都有对应的域名与其对应,除了__add、 __mul外,还有__sub(减)、 __div(除)、 __unm(负)、 __pow(幂),我们也可以定义__concat 定义连接行为。

    当我们对两个表进行加没有问题,但如果两个操作数有不同的 metatable 例如:
    在这里插入图片描述
    Lua 选择 metamethod 的原则:如果第一个参数存在带有__add 域的 metatableLua使用它作为 metamethod,和第二个参数无关;

    否则第二个参数存在带有__add 域的 metatableLua 使用它作为 metamethod 否则报错。

    Lua 不关心这种混合类型的,如果我们运行上面的 s=s+8 的例子在 Set.union 发生错误:

    C:\Users\Administrator\.vscode\extensions\actboy168.lua-debug-1.59.0\runtime\win32-x64\lua54\lua.exe: ...ments\Tencent Files\1978045947\FileRecv\Lua代码/main.lua:2593: attempt to 'add' a set with a non-set value
    stack traceback:
            [C]: in function 'error'
            ...ments\Tencent Files\1978045947\FileRecv\Lua代码/main.lua:2542: in metamethod 'add'
            ...ments\Tencent Files\1978045947\FileRecv\Lua代码/main.lua:2593: in main chunk
            [C]: in ?
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果我们想得到更加清楚地错误信息,我们需要自己显式的检查操作数的类型:

    function Set.union (a,b)
    if getmetatable(a) ~= Set.mt or
    getmetatable(b) ~= Set.mt then
    error("attempt to `add' a set with a non-set value", 2)
    end
    ... -- same as before
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    这4款浏览器必装插件,让浏览器使用体验上升100%
    普通人如何投资理财?
    S7-1200/1500程序设计规范指南之二:定义
    全志R128适配 ST7789v LCD
    SpringBoot+LayUI+MybatisPlus 前后端分离 实现数据表格下拉框功能
    CAN总线数据采集工具PCAN的使用教程
    LiveNVR监控流媒体Onvif/RTSP功能-Onvif 发现以及探测通过ONVIF添加摄像头监控直播及云台控制
    新零售行业如何玩转线上服务
    常见布局效果实现方案
    深入了解C++中各种不同意义的new和delete
  • 原文地址:https://blog.csdn.net/qq_44918090/article/details/126259957