我写了一个例子。
function readOnly(t)
local newTable = {}
local metaTable = {}
metaTable.__index = t
metaTable.__newindex = function(tbl, key, value) error("Data cannot be changed!") end
setmetatable(newTable, metaTable)
return newTable
end
local tbl = {
sex = {
male = 1,
female = 1,
},
identity = {
police = 1,
student = 2,
doctor = {
physician = 1,
oculist = 2,
}
}
}
local hold = readOnly(tbl)
print(hold.sex)
hold.sex = 2 --error
这意味着我可以访问表“tbl”的字段,但同时,我无法更改与该字段相关的值。
现在,问题是我想让所有嵌套表都拥有这个只读 property.How我如何改进“readOnly”方法?
答案 0 :(得分:5)
您只需递归地将readOnly
函数应用于内部表字段。您可以在__index
元方法中进行访问。您还应该缓存您创建的只读代理表,否则对内部表的任何读访问权(例如hold.sex
)都将创建一个新的代理表。
-- remember mappings from original table to proxy table
local proxies = setmetatable( {}, { __mode = "k" } )
function readOnly( t )
if type( t ) == "table" then
-- check whether we already have a readonly proxy for this table
local p = proxies[ t ]
if not p then
-- create new proxy table for t
p = setmetatable( {}, {
__index = function( _, k )
-- apply `readonly` recursively to field `t[k]`
return readOnly( t[ k ] )
end,
__newindex = function()
error( "table is readonly", 2 )
end,
} )
proxies[ t ] = p
end
return p
else
-- non-tables are returned as is
return t
end
end