模組 Forwardable
Forwardable
模組提供指定方法委派至指定物件的功能,使用 def_delegator
和 def_delegators
方法。
例如,假設您有一個包含陣列 @records
的類別 RecordCollection。您可以提供查詢方法 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
此外,如果您想要提供 size、<< 和 map 方法,它們全部委派至 @records,您可以這樣做
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!"
另一個範例¶ ↑
當您不想繼承超類別的所有方法時,您可以使用 Forwardable
作為繼承的替代方案。例如,以下是您如何將一系列 Array
執行個體方法新增至新類別 Queue
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 = Thread::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 進行全類別委派,請參閱 delegate.rb
。
常數
- FORWARDABLE_VERSION
- VERSION
forwardable.rb
版本
屬性
debug[RW]
已忽略
公開執行個體方法
def_instance_delegator(accessor, method, ali = method) 按一下以切換來源
將 method
定義為委派執行個體方法,並加上一個選用別名 ali
。對 ali
的 Method
呼叫會委派至 accessor.method
。accessor
應該是方法名稱、執行個體變數名稱或常數名稱。如果提供常數名稱,請使用至常數的完整路徑。傳回已定義方法的名稱。
class MyQueue CONST = 1 extend Forwardable attr_reader :queue def initialize @queue = [] end def_delegator :@queue, :push, :mypush def_delegator 'MyQueue::CONST', :to_i end q = MyQueue.new q.mypush 42 q.queue #=> [42] q.push 23 #=> NoMethodError q.to_i #=> 1
# File lib/forwardable.rb, line 188 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 mod = Module === self ? self : singleton_class ret = mod.module_eval(&gen) mod.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7' ret end
別名為:def_delegator
def_instance_delegators(accessor, *methods) 按一下以切換來源
定義多個委派方法的捷徑,但沒有提供使用不同名稱的規定。下列兩個程式碼範例具有相同的效果
def_delegators :@records, :size, :<<, :map def_delegator :@records, :size def_delegator :@records, :<< def_delegator :@records, :map
# File lib/forwardable.rb, line 156 def def_instance_delegators(accessor, *methods) methods.each do |method| next if /\A__(?:send|id)__\z/ =~ method def_instance_delegator(accessor, method) end end
別名為:def_delegators
instance_delegate
別名為:delegate