Include, Extend, And Prepend In Ruby
Ruby provides a feature to attach a specific behaviour/methods in the classes using the keyword
prepend. If we include a class with a module, it means we’re bringing in the module’s method as instance methods.
If we extend a class with a module method, it means we’re adding the methods which are added to class itself
and are available at class level. Prepending the module using
prepend is similar to the include.
include is the most common way of importing the module methods. When the module is called using the
in a class, ruby inserts the module into the ancestors chain, after it’s super class.
1 2 3 4 5 ```ruby > MyClass.ancestors => [MyClass, ModuleOne, Object, .....] ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 module ModuleOne def hello puts 'hello ModuleOne' end end class MyClass include ModuleOne def greet puts 'Good day !' end end
In above example, the
ModuleOne is included in the class. If we look the ancestor chain of MyClass we can see module
is present between the class and it’s ancestors. So, we can call methods defined in the class instances. For example
1 2 3 obj1 = MyClasse.new obj1.hello # hello ModuleOne
In contrast to the
include , including a module using
extend doesn’t inserts the module in the ancestor chain.
Due to which we can’t call the module method from the Class instances. Instead, Ruby inserts the module in the
singleton class of the MyClass.The singleton class is a class where the methods only for the specific
class are defined. The methods defined in this class is not acessible to any other class or the instances.
An example of using the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 module ModuleOne def hello puts 'hello ModuleOne for class' end end class MyClass extend ModuleOne def greet puts 'Good day !' end end puts MyClass.hello # hello ModuleOne for class puts Myclass.new.hello # error
It is also similar to the
include, except that instead of inserting the module between the class and it’s superclass
in the chain, it will insert the module to the bottom which mean before it’s class itself. When we call
a method from a instance, it will look into the module method even before looking to it’s class.
An example of using the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 module ModulePrepend def hello puts 'hello ModulePrepend' end end class MyClass prepend ModulePrepend def greet puts 'Good day !' end end obj = MyClass.new obj.hello #hello ModulePrepend
In above example, when
obj calls the
hello method, it initially search the
ModulePrepend in the ancestor chain.
1 2 3 4 ```ruby > MyClass.ancestors => [ ModulePrepend, MyClass, Object, .....] ```