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

  • 相关阅读:
    Spring 系列目录
    Netty 源码 ChannelHandler(四)编解码技术
    Netty 源码 ChannelHandler(三)概述
    Netty 源码 Channel(二)核心类
    Netty 源码 Channel(二)主要类
    NOIP 2017 PJ
    初学 Size Balanced Tree(bzoj3224 tyvj1728 普通平衡树)
    一文读懂后缀自动机 Suffix_Automata
    完美字符子串 单调队列预处理+DP线段树优化
    棋盘覆盖 状压DP+矩阵快速幂
  • 原文地址:https://www.cnblogs.com/softidea/p/5242953.html
Copyright © 2011-2022 走看看