参考帖子:
https://www.cnblogs.com/luweimy/p/4450276.html
配置表是肯定不允许在运行时更改的,所以有必要做成【只读】的table。
功能的实现大致分为三个部分
- 1.禁止在表中创建新值
- 2.禁止改变已有的值
- 3.将子表也变为只读
1.禁止在表中创建新值
使用__newindex元函数即可,它的作用就是在表赋新值时调用
local static = { exist={exist={exist=true}}, } setmetatable(static, {__newindex = function() assert(false, 'table is readonly ') end}) static['not-exist'] = false
这样给只读表赋一个新值,就会报错了.
2.禁止改变已有的值
这一项功能没有元函数直接提供,可以通过另一个方法巧妙的实现
原理:将传入的表作为返回表的元表__index,这样如果你想要改变值,就会转化为赋新值,这样就会调用元表的__newindex。
local readonly = function(t) local meta = { __index = t, __newindex = function() assert(false, 'table is readonly ') end, } local locked = {} setmetatable(locked, meta) return locked end local static = { exist={exist={exist=true}}, } static = readonly(static) static['exist'] = false
3.将子表也变为只读
此功能使用递归很好实现,只要对子表递归调用readonly函数即可。
local static = { exist={exist={exist=true}}, } local readonly readonly = function(t, deep) if deep then for k,v in pairs(t) do if type(v) == 'table' then t[k] = readonly(v, deep) end end end local meta = { __index = t, __newindex = function() assert(false, 'table is readonly ') end, } local locked = {} setmetatable(locked, meta) return locked end static = readonly(static, true) static['exist']['exist']['exist'] = false -- 打印表结构,如下图 print(inspect(static))
至此,readonly表就大成了,虽然其改变了表结果不过表用起来没什么变化
当前,它也存在问题,就是打印表不方便,很不直观,对调试可能会存在影响。
下面是使用inspect打印的表,看这样的表找字段数据,会有股蛋蛋的忧伤。。。
00