Forwardable
module Forwardable
可转换模块使用方法def_delegator和def_delegators将指定方法委托给指定的对象。
例如,假设你有一个RecordCollection类,它包含一个数组@records
。您可以提供查找方法record_number(),该方法只需在@records
数组中调用[] ,如下所示:
require 'forwardable'
class RecordCollection
attr_accessor :records
extend Forwardable
def_delegator :@records, :[], :record_number
end
我们可以像这样使用查找方法:
r = RecordCollection.new
r.records = [4,5,6]
r.record_number(0) # => 4
此外,如果您希望提供方法大小,<
class RecordCollection # re-open RecordCollection class
def_delegators :@records, :size, :<<, :map
end
r = RecordCollection.new
r.records = [1,2,3]
r.record_number(0) # => 1
r.size # => 3
r << 4 # => [1, 2, 3, 4]
r.map { |x| x * 2 } # => [2, 4, 6, 8]
您甚至可以使用Forwardable扩展常规对象。
my_hash = Hash.new
my_hash.extend Forwardable # prepare object for delegation
my_hash.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
my_hash.puts "Howdy!"
另一个例子
我们希望依靠之前明显发生的事情,但通过授权,我们可以只采用我们需要的方法,甚至适当地重命名它们。在许多情况下,这比继承更可取,这使我们可以使用完整的旧界面,即使其中大部分都不需要。
class Queue
extend Forwardable
def initialize
@q = [ ] # prepare delegate object
end
# setup preferred interface, enq() and deq()...
def_delegator :@q, :push, :enq
def_delegator :@q, :shift, :deq
# support some general Array methods that fit Queues well
def_delegators :@q, :clear, :first, :push, :shift, :size
end
q = Queue.new
q.enq 1, 2, 3, 4, 5
q.push 6
q.shift # => 1
while q.size > 0
puts q.deq
end
q.enq "Ruby", "Perl", "Python"
puts q.first
q.clear
puts q.first
这应该输出:
2
3
4
5
6
Ruby
nil
注意
请注意,RDoc不会检测委托方法。
forwardable.rb
通过#def_delegator和#def_delegators方法提供单方法委托。对于通过DelegateClass的full-class授权,请参阅delegate.rb
。
常量
FORWARDABLE_VERSION
forwardable.rb
版本
属性
debugRW
ignored
Public Instance Methods
def_delegator(accessor, method, ali = method)
Alias for: def_instance_delegator
def_delegators(accessor, *methods)
Alias for: def_instance_delegators
def_instance_delegator(accessor, method, ali = method) Show source
使用可选的别名名称定义method
为委托人实例方法ali
。方法调用ali
将被委托给accessor.method
。
class MyQueue
extend Forwardable
attr_reader :queue
def initialize
@queue = []
end
def_delegator :@queue, :push, :mypush
end
q = MyQueue.new
q.mypush 42
q.queue #=> [42]
q.push 23 #=> NoMethodError
# File lib/forwardable.rb, line 179
def def_instance_delegator(accessor, method, ali = method)
gen = Forwardable._delegator_method(self, accessor, method, ali)
# If it's not a class or module, it's an instance
(Module === self ? self : singleton_class).module_eval(&gen)
end
Also aliased as: def_delegator
def_instance_delegators(accessor, *methods) Show source
用于定义多个委托人方法的快捷方式,但没有规定使用不同的名称。以下两个代码示例具有相同的效果:
def_delegators :@records, :size, :<<, :map
def_delegator :@records, :size
def_delegator :@records, :<<
def_delegator :@records, :map
# File lib/forwardable.rb, line 152
def def_instance_delegators(accessor, *methods)
methods.delete("__send__")
methods.delete("__id__")
for method in methods
def_instance_delegator(accessor, method)
end
end
Also aliased as: def_delegators
delegate(hash)
Alias for: instance_delegate
delegate method → accessor Show source
delegate method, method, ... → accessor
以散列为参数。关键是一个符号或一系列符号。这些符号对应于方法名称。该值是该方法将被委派到的访问器。
# File lib/forwardable.rb, line 131
def instance_delegate(hash)
hash.each do |methods, accessor|
unless defined?(methods.each)
def_instance_delegator(accessor, methods)
else
methods.each {|method| def_instance_delegator(accessor, method)}
end
end
end
Also aliased as: delegate