您可以使用代理元表和有问题的空对象模式来解决此问题。空对象可能如下所示:
local Null = {}
local NullProto = { __index = function(t,k) return Null end }
setmetatable(Null, NullProto)
Null
当您尝试对其进行索引时,将始终返回自身。
该解决方案的关键思想是为原始表创建一个代理对象,它将使用以下逻辑:
- 如果原始表中不存在某些键,则返回 Null Object
- 如果原始表中存在某个键
- 如果引用的值是原始类型,则返回该值
- 如果引用的值是表类型,则用代理包装它并返回
代码可能看起来像这样
function make_safe_table(nonsafe)
local proto = {
__index = function(t, k)
local val = nonsafe[k]
if val == nil then
return Null
elseif type(val) == 'table' then
return make_safe_table(val)
else
return val
end
end
}
return setmetatable({}, proto)
end
你可以像这样使用这个函数:
local original = {
nested = {
deep = { hidden = 'value'}
},
simple = 'simple',
[3] = 'third'
}
local safe_original = make_safe_table(original)
print(safe_original.not_exists == Null) -- true
print(safe_original.nested.not_exists == Null) -- true
print(safe_original.nested.deep.not_exists == Null) -- true
print(safe_original.not_exists.still_not_exists == Null) -- true
print(safe_original.nested.deep.hidden) -- 'value'
print(safe_original.simple) -- 'simple'
print(safe_original[3]) -- 'third'
我不建议您在生产环境中使用此代码,因为它没有经过适当的测试,但我希望它能帮助您构建一个健壮的解决方案。有关元表的更多详细信息,请参见https://www.lua.org/pil/13.4.html。