如何在Ruby中扩展对象?实现装饰器式的对象方法扩展
Ruby中实现对象装饰器的简洁方案
当然可以实现,而且有比method_missing更简洁高效的方式,不用手动编写方法转发逻辑。
最直接的方案:用标准库的SimpleDelegator
Ruby标准库delegate模块里的SimpleDelegator就是专门做对象委托/装饰的工具,它会自动把所有未定义的方法转发给被包装的原对象,同时允许你给装饰后的对象单独添加新方法。
示例代码:
require 'delegate' # 原对象x,自带hello方法 x = Object.new def x.hello puts "Hello from original object" end # 创建装饰对象y y = SimpleDelegator.new(x) # 给y新增bye方法,还能直接调用x的方法 def y.bye hello # 直接调用原对象的hello puts "Bye from decorated object" end # 测试效果 y.hello # 输出:Hello from original object y.bye # 先输出Hello from original object,再输出Bye from decorated object
贴近你伪代码的封装写法
如果想让写法更接近你给出的伪代码(用块定义新增方法),可以自己封装一个extend方法:
require 'delegate' def extend(obj, &block) delegator = SimpleDelegator.new(obj) delegator.instance_eval(&block) delegator end # 使用方式和你的伪代码几乎一致 x = Object.new def x.hello puts "Hello from x" end y = extend(x) do def bye hello puts "Bye" end end y.hello # 输出Hello from x y.bye # 输出Hello from x 后再输出Bye
为什么比method_missing好
SimpleDelegator的方法转发基于Ruby原生的方法查找机制,性能比method_missing更高——后者每次调用未定义的方法都会触发缺失方法的判断逻辑,有额外运行开销;而SimpleDelegator只会在方法不存在时才转发,逻辑更高效,代码也更简洁,不需要自己处理方法转发的细节。
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

