如何在 lua 中实现只读 table?

How can I implement a read-only table in lua?

我写了一个例子。

 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

这意味着我可以访问 table "tbl" 的字段,但同时我不能更改与该字段相关的值。

现在,问题是我想让所有嵌套的 table 拥有这个只读 property.How 我可以改进 "readOnly" 方法吗?

您只需将 readOnly 函数也递归地应用于内部 table 字段。您可以在 __index 元方法中按访问方式执行此操作。您还应该缓存您创建的只读代理 tables,否则对内部 tables(例如 hold.sex)的任何读取访问都将创建一个新代理 table.

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