When we need to reuse code we could use inheriatance – create a new child class and add/override some methods. But it could lead to complex inheritance chains and extra methods which is not needed in a new class. Do we have a better alternative? Sure! It’s object composition.

Favor ‘object composition’ over ‘class inheritance’. (Gang of Four 1995:20)

Object composition allows us to create more reusable pieces of code that could be combined together keeping our code simple and understandable.

Let’s take an example of making a new interface over existing object. For example, we need a SimpleQueue class which is based on Array but have more idiomatic interface – enqueuing using enq method and dequeuing using deq method.

To achieve it we could just define those methods and call push and shift methods inside them:

1 2 3 4 5 6 7 8 9 10 11 12 13 class SimpleQueue def initialize @queue = [] end def enq ( value ) @queue . push ( value ) end def deq @queue . shift end end

Method delegation is commonly used so Ruby Stdlib have some sugar which helps us doing delegation on a method by method basis. Using Forwardable we’re able to delegate methods in declarative way:

1 2 3 4 5 6 7 8 9 10 11 12 require 'forwardable' class SimpleQueue extend Forwardable def initialize @queue = [] end def_delegator :@queue , :push , :enq def_delegator :@queue , :shift , :deq end

So def_delegator defines enq method as a call to push method on @queue object. The same with deq method.

There are also some array methods that could be useful for our queue object. We can easily delegate them all at once using def_delegators :

1 def_delegators :@queue , :clear , :first , :size

Here is an example of using a new SimpleQueue class which has a new interface based on the existing one:

1 2 3 4 5 6 queue = SimpleQueue . new queue . enq 1 , 2 , 3 , 4 queue . deq # => 1 queue . first # => 2 queue . size # => 3 queue . clear

And it’s important that SimpleQueue class has only methods that it has to have and doesn’t have any additional methods inherited from Array.

Forwardable library also includes a SingleForwardable module which might be useful in API client libraries. Consider we created an API client library with the following interface:

1 2 client = ApiLibrary :: Client . new client . some_api_call

It would be great to have an option to call API methods on a global client object instead of making a new client object every time we needed to do a request. We could use SingleForwardable to delegate methods to a global client object:

1 2 3 4 5 6 7 8 9 module ApiLibrary extend SingleForwardable def_delegators :client , :some_api_call , :another_api_call def self . client @client ||= Client . new end end

SingleForwardable defines methods on object which it’s called on. So def_delegators declaration creates class methods in the example above and makes possible to perform API calls without instantiating an API client object manually:

1 2 ApiLibrary . some_api_call ApiLibrary . another_api_call

If you were using both Forwardable and SingleForwardable in one class then you would need to call def_instance_delegator and def_single_delegator methods.

May objects be with you.