当前位置: 首页 > article >正文

lua:有关表访问的metamethod

针对在两种正常状态:表的不存在的域的查询和修改,Lua也提供了改变 tables的行为的方法。

index metamethod

我们可以通过index元方法来实现访问table内部不存在的域时人为操控返回数据。

比如以下测试代码:

local set = {1,2,3}
setmetatable(set,{
    __index = function (t, k)
        print("index func "..k)
    end
})
print(set[4]) --index func 4     nil

set = {}
print(set[4]) --nil

由上可以看出当我们去访问表内不存在的域时会走一遍__index函数并取得相应返回值。同时我们需要注意的是在后期重新赋值整表的时候其metatable已经刷新,所以再次访问不存在的域时已不存在之前的效果。

__index同样可以是一个table类型而非函数类型,这样的意义即如若访问不存在的域则寻找这个table B,否则则查找这个table B的__index metamethod。

local A = {1,2,3}
local B = {["a"] = 4,["b"] = 5}
setmetatable(B,{
    __index = function (t,k)
        print("test B index func")
    end
})
setmetatable(A,{
    __index = B
})
print(A["a"]) --4
print(A["b"]) --5
print(A["c"]) --test B index func

因此则可以引出lua的重要概念:继承,通过index函数可以实现没找到原table的域时可以从父类寻找。

如若不想经过index操作则直接调用rawget(t,i)来寻找相应值。

newindex metamethod

__newindex metamethod在对表缺少的域赋值的时候会被调用,注意,调用了__newindex之后并不会自动进行赋值操作,意味着在newindex函数里需要手动赋值才行。参考如下代码:

local A = {1,2,3}
setmetatable(A,{
    __newindex =function (t, k, v)
        print("test A newindex func")
    end
})
A[4] = 4 --test A newindex func
for i = 1,4 do
    print(A[i]) -- 1 2 3 nil
end

可以发现赋值了key=4之后的A[4]访问值依然为nil,说明newindex内部仍然需要显式加上t[k] = v才可。

如若不想经过newindex操作则直接调用rawset(t,k,v)来进行表的赋值。

默认值的表

直接重写index函数,如若访问到了不存在的域,则默认返回某值即可,参考如下代码:

local A = {1,2,3}
setmetatable(A,{
    __index = function (t, k)
        return 1
    end
})
for i = 1,4 do
    print(A[i]) -- 1 2 3 1
end

当然如果担心每个对象都需要默认值访问逻辑,但是默认值都不同,也可以表内部维护一个local table变量,__index实际上就是调用这个local变量里的某个键值对即可,如下所示:

local A = {1,2,3}
local key = {}
setmetatable(A,{
    __index = function (t, k)
        return A[key]
    end
})

A[key] = 1 --如果后续每个对象都需要不同的默认值,则直接修改即可,不用担心冲突
for i = 1,4 do
    print(A[i]) -- 1 2 3 1
end

监控表

顾名思义,当我们对某个表进行赋值或者访问操作时,需要进行记录。我们可以创建一个代理表,这个代理表不存储任何数据,修改__index和__newindex函数来输出记录并定位至原表,如下所示:

local A = {1,2,3}
function Record(tb)
    local proxy = {}
    setmetatable(proxy,{
        __index = function (t, k)
            print("index")
            return tb[k]
        end,
        __newindex = function (t, k, v)
            print("newindex")
            tb[k] = v
        end
    })
    return proxy
end

local proxy = Record(A)
for i = 1,3 do
    print(proxy[i])
--[[
    index
    1
    index
    2
    index
    3
    ]]--
end
proxy[4] = 4 --newindex

只不过类似pairs的操作是无效的,因为proxy本身就是空表。

只读表

参考之前的博客:lua只读表-CSDN博客


http://www.kler.cn/news/234570.html

相关文章:

  • 【DDD】学习笔记-精炼领域分析模型
  • 设计模式-观察者模式 Observer
  • 第77讲用户管理功能实现
  • 指针的基本含义及其用法
  • limit深度分页和优化思路
  • Docker 基本介绍
  • 正则可视化工具:学习和编写正则表达式的利器
  • excel统计分析——成组设计和配对设计
  • 微软 CMU - Tag-LLM:将通用大语言模型改用于专业领域
  • 医院挂号预约|医院挂号预约小程序|基于微信小程序的医院挂号预约系统设计与实现(源码+数据库+文档)
  • disql备份还原
  • 【开源】JAVA+Vue.js实现衣物搭配系统
  • 华为 huawei 交换机 接口 MAC 地址学习限制接入用户数量 配置示例
  • 车载测试Vector工具——常见问题汇总
  • 【C++】多态语法概念
  • springboot174基于springboot的疾病防控综合系统的设计与实现
  • Springboot 2.5.x如何集成Nacos 2.x的配置管理功能?
  • C语言之预处理详解
  • svg基础(八)滤镜-feTurbulence(湍流)
  • Elasticsearch:混合搜索是 GenAI 应用的未来
  • 服务器解析漏洞及任意文件下载
  • 【实验1】分布式模式的CentOS 6上安装Hadoop(1个master节点,2个slave节点)
  • ChatGPT 4:新特性与优势
  • postgresql 手动清理wal日志的101个坑
  • AI:125-基于深度学习的航拍图像中地物变化检测
  • 8 scala的共生对象
  • 小游戏和GUI编程(5) | SVG图像格式简介
  • 如何实现Vuex本地存储
  • 单片机学习笔记---AT24C02(I2C总线)
  • FATFS学习笔记——FATFS写文件的两种方式