如何在lua中实现只读表?

时间:2015-02-04 02:17:27

标签: lua readonly lua-table

我写了一个例子。

 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”方法?

1 个答案:

答案 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