Lua语法小贴士(五)元表与元方法

Lua里的元表(metatable)是指一套预定操作的集合,而这些操作称为元方法(metamethod)。

例如我们可以让两个数字相加,但是却没办法将两个table相加。如果想让表a加上表b,那么就需要使用元表里的__add元方法。

local tbl = {}
local mt = {}
mt.__add = function(a,b)
    return tbl.new(a.val + b.val)
end
function tbl.new(val)
    local t = {}
    setmetatable(t,mt)
    t.val = val
    return t
end

local a = tbl.new(1)
local b = tbl.new(2)
print((a+b).val)

元方法类似于c++里的运算符方法。

Lua里的算术操作除了__add之外,还有__mul(乘法)、__sub(减法)、__div(除法)、__unm(相反数)、__mod(取模)和__pow(乘幂)。此外还有__concat(连接)。

然后是关系操作:__eq(等于)、__lt(小于)和__le(小于等于),而对应的三种关系运算符(不等于,大于等于,大于)会通关前面的方法取反获得,不需要也不能实现。

接着是库定义的操作:__tostring(转字符串,print方法会自动调用这个元方法)

最后是访问操作:__index(索引)和__newindex(新索引),访问table的时候会优先访问table自身的索引,如果没有找到这个索引,会调用__index(查询)或__newindex(赋值)方法。

例如下面这段代码:

local tbl = {}
local mt = {
__index = function(t,k)
    print("index "..k)
    return rawget(t,k)
end,
__newindex = function(t,k,v)
    print("newindex "..k)
    rawset(t,k,v)
end
}
setmetatable(tbl,mt)
tbl.val = 1  --newindex val
tbl.val = 2
local val = tbl.val
local a = tbl.a --index a
我们可以借助这两个元反方实现一个只读的table:

local function readonly(t)
    local proxy = {}
    local mt = {
        _index = t,
        _newindex=function(t,k,v)
            error("!!Readonly!!", 2)
        end
    }
    setmetatable(proxy,mt)
    return proxy
end
local days = readonly({"Sun","Mon","Tue","Wed","Thu","Fri","Sat"})
print(days[1]) --Sun
days[2]="Noday" --!!Readonly!!
(此段代码改写自《Programming in Lua (Second Edition)》)

需要注意的两个点:

1、__index元方法可以直接使用原table代替函数,这样简单且高效。不过,需要每个只读代理都要创建一个新的元表。

2、这里使用了代理模式,可以参考小话设计模式(十二)代理模式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值