利用__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

时间: 2024-11-06 07:35:37

利用__index和__newindex实现默认值表、监控表、只读表(转)的相关文章

Lua中的__index和__newindex实例_Lua

前言 这篇博文将通过几个简单的实例演示,巩固对__index和__newindex的理解,同时加深对Lua中元表和元方法的理解,如果对Lua的元表和元方法还不是很熟悉的话,请参考这篇文章:<Lua中的元表与元方法>. 具有默认值的table 我们都知道,table中的任何字段的默认值都是nil,但是通过元表,我们可以很容易的修改这一规定,代码如下: 复制代码 代码如下: function setDefault(tb, defaultValue)      local mt = {__index

Lua中__index和__newindex之间的沉默与合作_Lua

因为不想在一篇文章里挤太多知识点,所以,有些小知识点就集合到这样的文章里吧~ 1.沉默技能--拒绝__index和__newindex效果 虽然__index和__newindex是很好用的功能,但是,有时候我们又希望很纯粹地去调用table或者给table赋值. 那,这时候怎么办?给table重新设置一个元表?不,这个做法很糟糕~ 于是,体贴的Lua又给我们提供了这样的调用方式,如下代码: 复制代码 代码如下:     local smartMan = {         name = "no

怎么监控oracle数据库表和表空间

  怎么监控oracle数据库表和表空间的现状 declare unf number; unfb number; fs1 number; fs1b number; fs2 number; fs2b number; fs3 number; fs3b number; fs4 number; fs4b number; full number; fullb number; begin dbms_space.space_usage('&1', '&2', 'TABLE', unf, unfb, fs

excel的默认新建3个工作表数目怎么更改?

  打开EXCEL默认打开工作表的数目为三个,这个往往是满足不了我们的需求的,虽然手动添加可以达到母的,但这并不是长久之法,如果要是能够更改默认的工作表数目,这个问题便可迎刃而解,那么excel的默认工作表数目怎么更改?下面就为大家详细介绍一下! 方法/步骤 1,启动excel2007,并单击office按钮,在弹出的下拉菜单中单击"excel选项"按钮. 2,弹出"excel选项"对话框,此时左侧窗格中默认选中的是"常用"选项. 3,在&quo

jquery-select下拉表中 有默认值 如何排除默认值判断select下表是否选择没选择提示

问题描述 select下拉表中 有默认值 如何排除默认值判断select下表是否选择没选择提示 <td> <select id=""applicationamount3"" name=""applicationamount""> <option value=""2"" selected=""selected"" >

jq 点击文本域清除默认值与回车提交表单代码

jq 点击文本域清除默认值与回车提交表单代码 点击文本域,清除默认值.默认值显示时为灰色文字,点击后高亮显示,可绑定回车事件. 项目中常用到的一个效果,封装成一个小小的插件,一点不复杂,需要的看下demo演示中源码注释.若是不想只为清除一个默认文本调一个jquery库,可以用原生的按我的思路写一下,很简单. 特点 1.支持input文本域及textarea同时为多表单添加同样的默认值; 2.默认值可通过表单value值设定,也可通过插件参数(iset.curval)设置. iset.curval

利用SQL Server数据库邮件服务实现监控和预警_MsSql

背景 现在越来越多的企业.公司要求对于数据库实现7*24小时的数据库监控,一般情况下采用的就是第三方的平台来实现邮件和手机短信的监测提醒.前几日公司新上了一台服务器,急于部署程序还没来得及搭建其他相关平台,为了更好的监控数据库,暂时用SQL Server自带的邮件服务来实现对数据库的监控和预警.下面简要介绍下配置的过程便于以后使用. 配置邮件 整个部分的核心就是配置邮件服务,这部分需要一个邮件账户以及相应的邮件服务器.下面就以QQ的邮件为例进行说明. 1.设置邮件服务器 开启SMTP服务,点击开

利用SQL Server数据库邮件服务实现监控和预警

背景 现在越来越多的企业.公司要求对于数据库实现7*24小时的数据库监控,一般情况下采用的就是第三方的平台来实现邮件和手机短信的监测提醒.前几日公司新上了一台服务器,急于部署程序还没来得及搭建其他相关平台,为了更好的监控数据库,暂时用SQL Server自带的邮件服务来实现对数据库的监控和预警.下面简要介绍下配置的过程便于以后使用. 配置邮件 整个部分的核心就是配置邮件服务,这部分需要一个邮件账户以及相应的邮件服务器.下面就以QQ的邮件为例进行说明. 1.设置邮件服务器 开启SMTP服务,点击开

Oracle中利用数据泵导出查询结果(二) 外部表的卸载功能

还是上一篇中的测试环境: SQL> CREATE TABLE T1 2  (ID NUMBER, NAME VARCHAR2(30)); Table created. SQL> INSERT INTO T1 2  SELECT ROWNUM, TNAME 3  FROM TAB; 66 rows created. SQL> CREATE TABLE T2 2  (ID NUMBER, NAME VARCHAR2(30)); Table created. SQL> INSERT IN