Ruby Modules and Inheritance Tutorial

  • Post author:
  • Post category:Ruby

In this section, we will learn how to use modules and class inheritance together in Ruby.

Note: we’re assuming you’re already familiar with Ruby Modules.

Order of Execution in Ruby Classes with Modules and Parent Class

When including a module into the body of a class (mixin) and that class has inherited from another class as well, one question that might pop up is that what’s the order of execution in such scenario then?

Well, the answer is, your modules comes between the parent class and the child class!

For example, let’s say we have a class name `A` and it’s the parent class of the class `B`. Now the class B here included a module named `MyModule` into its body.

Here, if we create an object from the class B and call a method on top of it, this will be the order of execution:

  1. Your program will first check the body of the class B to see if it has the specified method or not.
  2. If the method was in the body of the class B then it is invoked. Otherwise, your program will move on to the body of the `MyModule` to search that module for the specified method.

Note that the super class A is not searched yet! This means modules have higher precedence compared to parent classes! And so they will be searched first.

Now, if the modules also didn’t have the specified method, then in that case your program will start to search the body of the parent classes.

Note: if you have multiple modules in the body of a class, they all will be searched for the specified method.

Example: using modules and inheritance in a Ruby class

class Human 
    def print_name 
        puts "Hello from Human class" 
    end 
end 
module PrintFullName
    def print_name
        puts first_name, last_name, age, id 
    end 
end 

class Person < Human

    include PrintFullName 

    attr_accessor :first_name, :last_name, :age, :id 

    def initialize (first_name, last_name, age, id)
        self.first_name = first_name
        self.last_name = last_name 
        self.age = age 
        self.id = id 
    end 
end 	

prs = Person.new("John","Doe",100, 43221)

prs.print_name

Output:

John

Doe

100

43221

You can see that the `Person` class is inheriting from `Human` class as well as mixed in the `PrintFullName` module.

The Human class and PrintFullName` module both have a method named `print_name`.

So now when we call the method using the `prs` object, first the body of the Person class is searched, after that comes to the `PrintFullName` module (because the Person class didn’t have the mentioned method) and now because the module has the method then it is invoked and no call to the parent class (Human) will be made in this example.

Ruby ancestors Method

If you’re interested to see the order of search for a method on a class, there’s a method named `ancestors` which will return the list of classes and modules and their priorities on which your program will search them first for the target method.

Simply call this method on top of the target class and you’ll get the list back.

Example: using ancestors method in Ruby

class Human 
    def print_name 
        puts "Hello from Human class" 
    end 
end 
module PrintFullName
    def print_name
        puts first_name, last_name, age, id 
    end 
end 

class Person < Human

    include PrintFullName 

    attr_accessor :first_name, :last_name, :age, :id 

    def initialize (first_name, last_name, age, id)
        self.first_name = first_name
        self.last_name = last_name 
        self.age = age 
        self.id = id 
    end 
end 	

prs = Person.new("John","Doe",100, 43221)

puts Person.ancestors

Output:

Person

PrintFullName

Human

Object

Kernel

BasicObject

Leave a Reply