zoukankan      html  css  js  c++  java
  • 利用__index和__newindex实现默认值表、监控表、只读表(转)

    __index和__newindex实际上相当于是在读写表的时候分别加了一道过滤的逻辑,让读写表的操作可以被监控或说回调,利用这个特性可以实现一些带有特殊功能的表。

      带有默认值的表:

    复制代码
    setdefault = function(t, v)
        setmetatable(t, {__index = function () return v end})
    end
    
    s = {1, 2, 3}
    setdefault(s, 0)        -- 默认值设为0
    print(s.x)
    复制代码

      一般访问不存在的域会返回nil,但经过上面代码处理后,访问不存在的域会返回一个默认值。为了实现公用metatable,可以将代码封装如下:

    key = {}
    local mt = {__index = function (t) return t[key] end}
    function setdefault(t, d)
        t[key] = d
        setmetatable(t, mt)
    end

      监控表(代理表):

    复制代码
    t = {} --需要监控的表
    local _t = t
    t = {} --代理表需要为空,因为只有当读写不存在的域时,才会触发__index和__newindex
    
    local mt = {
        __index = function (t, k)
        print("*access to element"..tostring(k))
        return _t[k]
        end,
        
        __newindex = function(t, k, v)
        print("*update of element " .. tostring(k) .. " to " .. tostring(v))    
        _t[k] = v
        end
    }
    
    setmetatable(t, mt)
    
    t[2] = 'hello'
    print(t[2])
    复制代码

      对上述代码进行一些适当的封装,将原始表作为代理表的一个特殊的域对应的值:

    复制代码
    local index = {}
    
    local mt = {
        __index = function (t, k)
            print("*access to element " .. tostring(k))
            return t[index][k]
        end,
    
        __newindex = function (t, k , v)
            print("*update of element " .. tostring(k) .. " to " .. tostring(v))
            t[index][k] = v
        end
    }
    
    track = function (t)
        local proxy = {}
        proxy[index] = t
        setmetatable(proxy, mt)
        return proxy
    end
    
    t = track(t)
    复制代码

      只读表:

    复制代码
    function readOnly(t)
        local proxy = {}
        local mt = {
            __index = t,
            __newindex = function (t, k, v)
                error("attemp to uopdaate a read-only table", 2)
            end
        }
    
        setmetatable(proxy, mt)
        return proxy
    end
    
    days = readOnly{"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"}
    print(days[1])
    days[2] = "Noday"
    复制代码

      上述利用__index和__newindex特性来实现的一些具有特殊表的方法都比较简单易懂,而且很好用。

    http://www.cnblogs.com/sifenkesi/p/3837944.html

  • 相关阅读:
    nowcoderD Xieldy And His Password
    Codeforces681D Gifts by the List
    nowcoder80D applese的生日
    Codeforces961E Tufurama
    Codeforces957 Mahmoud and Ehab and yet another xor task
    nowcoder82E 无向图中的最短距离
    nowcoder82B 区间的连续段
    Codeforces903E Swapping Characters
    Codeforces614C Peter and Snow Blower
    Codeforces614D Skills
  • 原文地址:https://www.cnblogs.com/softidea/p/5242953.html
Copyright © 2011-2022 走看看