在 Ruby 中的 forwardable 模块 ( 上 ) 章节中,我们介绍了 forwardable
模块的一些基本用法。在日常使用过程中,这其实已经足够了。但 forwardable
模块还是有些知识没讲解,我们这章就统一讲完吧。
本章节,我们将会涉及到以下几个知识点
SingleForwardable
模块- 添加行为 ( behavior ) 到对象中
- 添加行为 ( behavior ) 到一个类或模块中
SingleForwardable 模块
SingleForwardable
是一个模块,主要的功能就是添加行为到一个对象、一个类或一个模块中。
在 Ruby 内部实现时,使用了 extend 关键字将此模块包含进 singleton 类,为此可以在类级别向类添加方法 ( 保持简单 )
添加行为到对象中
让我们分析下 Ruby 官方文档提供的示例
# in single_forwardable.rb require 'forwardable' printer = String.new printer.extend SingleForwardable printer.def_delegator "STDOUT", "puts" printer.puts "Howdy!"
输出结果为
?> ruby single_forwardable.rb Howdy!
在这个示例中,printer
是 String
的一个实例。
此对象扩展自 SingleForwardable
模块。这意味着SingleForwardable
模块内的方法将被添加到 printer
对象的单例类中。因此,只有 String 的这个特定实例 printer
才能使用 SingleForwardable 模块的属性
然后我们使用 printer.def_delegator
方法将对 printer.puts
的任何调用转发给 STDOUT
( 标准输出 )
这就是为什么我能能在终端上看到 Howdy!
forwardable 模块也能实现这个功能,但为了单一职责原则,也为了清楚起见,总是喜欢使用SingleForwardable 模块
添加行为到一个类或模块
同样的,让我们分析下 Ruby 官方文档提供的示例
# in single_forwardable.rb require 'forwardable' class Implementation def self.service puts "serviced!" end end module Facade extend SingleForwardable def_delegator :Implementation, :service end Facade.service
输出结果如下
$> ruby single_forwardable.rb serviced!
在这个范例中,Implementation 类定义了一个名为 service 的类方法
然后,将 Facade
扩展自 SingleForwardable
最后,调用 def_delegator
方法。
调用 def_delegator
方法时,第一个参数 :Implementation
是一个类,是消息的接收器,第二个参数 :service
就是实际的消息
这意味着对 Facade.service 的任何调用都会自动将 service
消息转发给 Implementation
接收器