LUA - 创建元表,使每个子表也成为一个元表
2020-12-2 10:56:51
收藏:0
阅读:182
评论:1
但这肯定会让人感到困惑。
我对LUA还很陌生,其中一个我尚未深入研究的问题就是元表。
我需要找到一种方法来创建一个元表,在编辑值时运行函数。如果我保持在“一个级别”上,也就是第一个索引,那么这不是问题。然后我可以简单地使用__newindex来运行它。但是我正在尝试的是无论修改什么值都运行该函数。
这将需要某种方式将元表内的任何表再次设置为运行与“主”元表相同的函数的元表
在我的用例中,这将是一个“保存”函数:
function MySaveFunction(tbl)
FileSave(my_settings_path, tbl)
end
MyTable = setmetatable()
MyTable.Value = value --> 运行MySaveFunction(MyTable.Value)
MyTable.SubTable = {} --> 在SubTable上运行setmetatable()
MyTable.SubTable.Value = value --> 运行MySaveFunction(MyTable.SubTable.Value)
MyTable.SubTable.SubSubTable = {} --> 在SubSubTable上运行setmetatable()
MyTable.SubTable.SubSubTable.Value = value --> 运行MySaveFunction(MyTable.SubTable.SubSubTable.Value)
MyTable.SubTable.SubSubSubTable = {} --> 在SubSubSubTable上运行setmetatable()
MyTable.SubTable.SubSubSubTable.Value = value --> 运行MySaveFunction(MyTable.SubTable.SubSubSubTable.Value)
希望有人能帮我 <.<
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

首先需要注意的是,
__newindex和__index元方法只在处理目标表中的nil值时触发。如果想要追踪每个变化,就不能只使用__newindex,因为一旦写入一个值,后续调用将不会做任何事情。相反,需要使用代理表。另一个需要考虑的重要问题是跟踪访问成员的路径。
最后,还需要记住在实现处理程序时使用原始访问函数,例如
rawget。否则,可能会遇到堆栈溢出或其他奇怪的行为。让我们举个简单的例子来说明这些问题:
local mt = {} function mt.__newindex (t, key, value) if type(value) == "table" then rawset(t, key, setmetatable(value, mt)) -- 为嵌套表设置元表 -- 在这里使用 `t[key] = setmetatable(value, mt)` 会导致溢出。 else print(t, key, "=", value) -- 我们希望在标准输出中看到每次写入。 rawset(t, key, value) end end local root = setmetatable({}, mt) root.first = 1 -- table: 0xa40c30 first = 1 root.second = 2 -- table: 0xa40c30 second = 2 root.nested_table = {} -- /nothing/ root.nested_table.another = 4 -- table: 0xa403a0 another = 4 root.first = 5 -- /nothing/现在,我们需要处理它们。让我们先从创建代理表的方法开始:
local function make_proxy (data) local proxy = {} local metatable = { __index = function (_, key) return rawget(data, key) end, __newindex = function (_, key, value) if type(value) == "table" then rawset(data, key, make_proxy(value)) else print(data, key, "=", value) -- 或者你的保存函数在这里! rawset(data, key, value) end end } return setmetatable(proxy, metatable) -- setmetatable() 简单地返回 `proxy` end这样,你有三个表:proxy_、_metatable 和 _data_。用户访问 _proxy_,但因为每次访问它时都是完全空的,所以从 metatable 中调用
__index或__newindex元方法。这些处理程序访问 data 表格,以检索或设置用户感兴趣的实际值。以与前面相同的方式运行并改善代码:
local root = make_proxy{} root.first = 1 -- table: 0xa40c30 first = 1 root.second = 2 -- table: 0xa40c30 second = 2 root.nested_table = {} -- /nothing/ root.nested_table.another = 4 -- table: 0xa403a0 another = 4 root.first = 5 -- table: 0xa40c30 first = 5这应该让你了解在这里为什么要使用代理表以及如何处理其元方法。
剩下的问题就是如何确定要访问的字段的路径。这部分在 另一个问题的另一个答案 中有涉及。我不觉得有必要重复它。