lua中如何保证表只读?
手游开发过程中,基于热更的考虑,大多数会使用lua这种解释性语言作为编程语言,那么开发过程中经常会使用配置表,如何保证配置表只读呢? 即不希望业务那边修改到配置表
首先看一个无任何处理手段的代码
local t = {12, 13, 25}
print(t[1])
t[1] = 1
print(t[1])
运行后t[1]变为了1,很轻松就被修改了
解决方案步骤1:使用元表,禁止用户访问
local t = {12, 13, 25}
local config = setmetatable({}, {
__index = t,
__newindex = function(t, k , v)
print('不允许设置')
end
})
print(config[1])
config[1] = 1
print(config[1])
核心思想是,用一个空table作为代理,业务通过这个空table获取对应配置时,背后会通过__index元方法来获取,但是业务set时,我们通过_newindex来拒绝
但是此方案带来一个新的问题,我们发现无法使用ipairs或者pairs进行遍历了,因此需要加点东西,元表中设置一下__pairs和__ipairs
local config = setmetatable({}, {
__index = t,
__ipairs = function(table)
return ipairs(t)
end,
__pairs = function(table)
return pairs(t)
end,
__newindex = function(t, k , v)
print('不允许设置')
end
})
总结
新建一个接口,用于对配置表进行只读设定
function readOnly(originalTable)
local proxy = {}
local mt = {
__index = function(t, key)
return originalTable[key]
end,
__newindex = function(t, key, value)
error("Attempt to modify a read-only table", 2)
end,
__pairs = function(t)
return pairs(originalTable)
end,
__ipairs = function(t)
return ipairs(originalTable)
end,
__metatable = false -- 禁止修改元表
}
setmetatable(proxy, mt)
return proxy
end
接下来对配置表进行调用即可,比如
-- 示例表
local myTable = {
a = 1,
b = 2,
c = 3
}
-- 创建只读表
local myReadOnlyTable = readOnly(myTable)
遗留问题
- rawset写法。设置元表阻止不了这种写法,那么怎么处理这种情况呢?解决方案todo