File: forwardable.rb

# forwardable.rb

Path: | forwardable.rb
Last Update: | Sat Oct 15 23:44:27 AUS Eastern Standard Time 2005

# forwardable - Support for the Delegation Pattern

       $Release Version: 1.1$
       $Revision: 1.2.2.1 $
       $Date: 2005/09/26 13:59:45 $
       by Keiju ISHITSUKA(keiju@ishitsuka.com)

       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. You can use Forwardable to setup this delegation at the class level, or SingleForwardable to handle it at the object level.

## 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 prefered 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

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

Prints:

       Howdy!

[Validate]