Lua风格的封装

封装是很多OO程序员的思维定势,似乎只要封装了,世界就完美了。
其实封装并不能解决问题,只能隐藏问题。
我在这里并不打算讨论好的封装和坏的封装。只是想介绍一下Lua的封装惯用法。

先看一个例子:


module('modulename', package.seeall)--创建一个名为 'modulename' 的table
local function index_function(o, k)--作为表的索引函数
local v = rawget(o, '_mt')[k]--_mt=modulename
if v then return v end --如果在'_mt'表中找到,就直接返回,即元表优先于原型
--自此说明没有在元表中找到
local base = rawget(o, '_proto')--如果被所以的表有'_proto'项,就将其视为原型
--自此base就是原型
if base then --若有原型就参考原型
v = base[k] --在原型中查找
if type(v) == "function" then--这里是为了实现原型的函数操作原型,而不是操作o
return function(x,...)--这里返回一个闭包(函数),如果对闭包还有不理解的请自行查阅Google
return v(base,...)--v是一个upvalue,base也是,这里把x(也就是第一个参数,也就是table)丢弃了,因为将用原型中的函数取代之
end
else
return v--如果v不是个函数,就可以直接返回,
end
end
--如果没有设置原型,那就算了,
end


modulename.__index=modulename
local metatable = {__index =index_function, -- __index 函数设置在metatable里才有用
__mode="v",--表明是值是weak引用
__tostring=function(o)--这个是花边功能
return 'modulename:'..tostring(o._proto)
end
}

--对外的接口函数
function wrap(nudity, xxx)--nudity表示裸露的待包装的对象(table)
local xxx= xxx or nudity.xxx ;--这里随便填默认值,卡卡
--注意,元表_mt优先于原型,这个符合包装语义,_mt中的方法会替代_proto中的方法。
return setmetatable({_proto=nudity, _mt =modulename, xxx = xxx}, metatable)--这里的两个xxx不相同的,卡卡
end

这个例子,实现了对任一个对象,附加一个包装的功能。
可以用在把一个异步接口或者一个非阻塞同步接口转换到伪阻塞协程接口时使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值