We'd discussed about include
method in the The RubyMonk Primer: Modules chapter. include
makes it possible to share behaviour through modules by mixing in the methods from a module into a class.
However, include
has a limitation: it can only add instance level methods - not class level methods. Lets look at an example:
As you can see, we receive a NoMethodError
when trying to invoke the module level method from the class.
But there are occasions when you would want to include some methods from a module as class-level methods in a class. This is where the method extend
becomes useful.
The extend
method works similar to include
, but unlike include
, you can use it to extend any object by including methods and constants from a module.
Here is an example:
The important thing to note here is that extend
works everywhere: inside a class/module definition and on specific instances. include
however cannot be used on specific objects.
In a sense, extend
can be used to mimic the functionality of the include
method. Let us discuss this aspect a bit: when you add an include
statement inside a class defintion, Ruby ensures that all new instances of the class will have the methods defined in the included module.
So, to mimick include
, you'll have to reproduce what Ruby does for you when using include
. That means you'll have to add all the methods present in the mixin module to every new instance of the class. The next exercise is to do just that!
These bits of information will help you with the exercise:
- Ruby always calls the instance method
initialize
whenever it builds a new instance of a class
- The
self
keyword can be used to get a handle on the current instance - even inside the initialize
method
- Once we get a handle on the instance when it is being created, we can just
extend
the module and achieve the desired result
Well, that is all you need to know! Now get going and make those tests green!
That should have been an interesting exercise!
However, it was meant to only demonstrate how you can use extend
to mimick include
. You should not use that approach where the include
method would work. include
is the standard Ruby idiom for mixing in methods from a module to a class and you should stick to it.