module Forwardable
Das Modul Forwardable bietet die Delegation von angegebenen Methoden an ein bestimmtes Objekt unter Verwendung der Methoden def_delegator und def_delegators.
Angenommen, Sie haben eine Klasse RecordCollection, die ein Array @records enthält. Sie könnten die Lookup-Methode record_number() bereitstellen, die einfach [] auf dem @records-Array aufruft, wie folgt:
require 'forwardable' class RecordCollection attr_accessor :records extend Forwardable def_delegator :@records, :[], :record_number end
Wir können die Lookup-Methode wie folgt verwenden:
r = RecordCollection.new r.records = [4,5,6] r.record_number(0) # => 4
Wenn Sie außerdem die Methoden size, << und map bereitstellen möchten, die alle an @records delegiert werden, können Sie dies so tun:
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]
Sie können sogar reguläre Objekte mit Forwardable erweitern.
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!"
Ein weiteres Beispiel
Sie könnten Forwardable als Alternative zur Vererbung verwenden, wenn Sie nicht alle Methoden von der Superklasse erben möchten. Hier ist zum Beispiel, wie Sie einer neuen Klasse Queue eine Reihe von Array-Instanzmethoden hinzufügen könnten:
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
Dies sollte ausgeben:
2 3 4 5 6 Ruby nil
Hinweise
Beachten Sie, dass RDoc delegierte Methoden nicht erkennt.
forwardable.rb bietet die Einzelmethoden-Delegation über die Methoden def_delegator und def_delegators. Für die Delegationsklasse über DelegateClass siehe delegate.rb.
Constants
- FORWARDABLE_VERSION
-
Version für Abwärtskompatibilität
- VERSION
-
Version von forwardable.rb
Attribute
ignoriert
Öffentliche Instanzmethoden
Source
# 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 mod.module_eval(&gen) end
Definiert method als delegierende Instanzmethode mit einem optionalen Aliasnamen ali. Methodenaufrufe an ali werden an accessor.method delegiert. accessor sollte ein Methodenname, ein Instanzvariablenname oder ein Konstantenname sein. Verwenden Sie den vollständigen Pfad zur Konstanten, wenn Sie den Konstantenamen angeben. Gibt den Namen der definierten Methode zurück.
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
Source
# 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
Abkürzung für die Definition mehrerer delegierender Methoden, jedoch ohne die Möglichkeit, einen anderen Namen zu verwenden. Die folgenden beiden Codebeispiele haben die gleiche Wirkung:
def_delegators :@records, :size, :<<, :map def_delegator :@records, :size def_delegator :@records, :<< def_delegator :@records, :map
Source
# File lib/forwardable.rb, line 135 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