Lua 设置table为只读属性

原文大佬链接:http://www.cnblogs.com/vanishfan/p/6909153.html

下面写一下自己能够理解的想法和思路:
1,利用元方法__newindex的特性(对字段进行赋值的时候如果表中没有则执行__newindex中的方法),新建一个空表代替原来的表,并对空表进行元方法重写实现table的相应功能。这样对任何字段的修改,在空表中肯定都找不到,只能只能统一的入口方法__newindex,我们不处理就能实现只读。
2,再利用__index元方法保存原来的表, 因为取值的时候如果找不到就会去__index中取。
利用以上两个元方法的特性实现table的只读。

自己重新写了一遍,并添加注释:

local function read_only(inputTable)
    -- 避免table 互相引用,加入tempTable建立索引,存储已经处理过的table
    local tempTable = {}

    local function __read_only(tbl)
        -- 正常如果没有互相引用,都会走处理逻辑
        if not tempTable[tbl] then
            -- 取到table的元表,如果没有则创建一个空table,并设置成元表,目的:下次直接可以从table的元表里取处理过的只读table
            local mt = getmetatable(tbl)
            if not mt then
                mt = {}
                setmetatable(tbl, mt)
            end

            -- 取到元表里的__read_only_proxy字段(处理过的只读table),没有则创建
            local proxy = mt.__read_only_proxy
            if not proxy then
                proxy = {}
                -- 再设置回去
                mt.__read_only_proxy = proxy
                -- 重要的处理逻辑,设置空table的元表数据
                local tbl_mt = {
                    __index = tbl,  -- 取数据
                    __newindex = function(t,k,v) print("can not write!") end,  -- 写数据会报错
                    __pairs = function(t) return pairs(tbl) end, -- 重写遍历
                    __len = function(t) return #tbl end,  -- 重写获取长度
                    __read_only_proxy = proxy,  -- 这里也设置一下,方便获取
                }

                setmetatable(proxy, tbl_mt)
            end

            -- 保存
            tempTable[tbl] = proxy

            -- 递归处理table里面的table
            for k, v in pairs(tbl) do
                if type(v) == "table" then
                    tempTable[k] = __read_only(v)
                end
            end
        end
        
        -- 返回保存的数据
        return tempTable[tbl]
    end

    return __read_only(inputTable)
end

测试:

local t0 = {key1 = 1, key2 = 2}
local t1 = read_only(t0)

for i,v in pairs(t1) do
    print("key: " .. i .. "\t v: " .. v)
end
--[[
    key: key2	 v: 2
    key: key1	 v: 1
]]

print(#t1)  -- 0
t1.key1 = 3  -- can not write!
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值