2015-02-04 4 views
3

Я написал пример.Как можно использовать таблицу только для чтения в 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 

Это означает, что я могу дать доступ к полю таблицы «ТПС», но в то же время, я не могу изменить значение, связанное с полем.

Теперь проблема заключается в том, что я хочу, чтобы все вложенные таблицы имели это свойство только для чтения .Как можно улучшить метод readOnly?

ответ

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 
Смежные вопросы