Last Modified
2019-05-06 17:38:51 -0500
Requires

Description

forwardable.rb - 
    $Release Version: 1.1$
    $Revision: 24174 $
    by Keiju ISHITSUKA(keiju@ishitsuka.com)
    original definition by delegator.rb
    Revised by Daniel J. Berger with suggestions from Florian Gross.

    Documentation by James Edward Gray II and Gavin Sinclair

Introduction

This library allows you delegate method calls to an object, on a method by method basis.

Notes

Be advised, RDoc will not detect delegated methods.

forwardable.rb provides single-method delegation via the def_delegator() and def_delegators() methods. For full-class delegation via DelegateClass(), see delegate.rb.

Examples

Forwardable

Forwardable makes building a new class based on existing work, with a proper interface, almost trivial. We want to rely on what has come before obviously, but with delegation we can take just the methods we need and even rename them as appropriate. In many cases this is preferable to inheritance, which gives us the entire old interface, even if much of it isn't needed.

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

Prints:

2
3
4
5
6
Ruby
nil

SingleForwardable can be used to setup delegation at the object level as well.

printer = String.new
printer.extend SingleForwardable        # prepare object for delegation
printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
printer.puts "Howdy!"

Also, SingleForwardable can be use to Class or Module.

module Facade
  extend SingleForwardable
  def_delegator :Implementation, :service

  class Implementation
     def service...
  end
end

If you want to use both Forwardable and SingleForwardable, you can use methods def_instance_delegator and def_single_delegator, etc.

If the object isn't a Module and Class, You can too extend Forwardable module.

printer = String.new
printer.extend Forwardable              # prepare object for delegation
printer.def_delegator "STDOUT", "puts"  # add delegation for STDOUT.puts()
printer.puts "Howdy!"

Prints:

Howdy!