Modules is a way to achieve Polymorphism is Ruby. A module is a collection of behaviors that can be included in another class via mixins.
Modules are usefull because Ruby is a single inheritance language: a class can only inherits from one superclass. This limitation makes it difficult to design accurately a problem. Modules let the programmer mix in behaviors to achieve what would be otherwise impossible with a single inheritance. A class can sub-class from only one parent (superclass) but it can mix in as many modules as it likes.
Module cannot be instantiated (no object can be created from a module). They are only used for mixins and namespacing.
Mixins comes from “mixed in”: a module is mixed in (mixin) to a class using the
include method invocation.
As Ruby’s class can only inherits from one superclass, one can use module and mixins to group common behaviors to create a more flexible design.
module Speakable def speak(sound) puts sound end end class Flamingo include Speakable end johnny = Flamingo.new johnny.speak('Gwa gwa!') # => Gwa gwa!
See Method Lookup Path for how Ruby lookup methods of module mixed in to a class.
Namespacing means grouping similar classes under a common module. Using namespacing has two advantages:
- Better organize and recognize related classes in our code
- Reduce the likelihood of our custom classes to collide with classes of the same name in the codebase (specially true when using a lot of gems)
module Mammal class Dog end class Cat end end olive = Mammal::Dog.new felix = Mammal::Cat.new
Classes in a module are called using two colons:
Container (for methods)
Using modules as a container for methods (called module methods) let us define methods that quite don’t match any class and/or module in our codebase.
module Speakable # Other methods def self.out_of_place_method(num) num**2 end end result = Speakable.out_of_place_method(4) # Preferred way to call the method result = Speakable::out_of_place_method(4)