So How Does It Behave?

Let’s say you have the following classes:

The Dog class inherits from the Animal class, which defines a #speak method.

So we can do the following:

dog = Dog.new

=> #<Dog:0x00007ff5b78e9270> dog.speak

"I am from the Animal class"

=> "I am from the Animal class"

By simple inheritance, our instance of the Dog class has access to its parent’s #speak method.

But how exactly does Ruby know where to find this method?

Well, it’s quite simple.

It checks the object on which the method is called (in this case, an instance of the Dog class) using an approach similar to the following:

The #instance_methods returns, as the name suggests, the methods of an instance as an array. In this case, Dog.instance_methods returns a bunch of methods inherited from its ancestors, including our #speak method:

Dog.instance_methods => [:speak, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, ...]

But this isn’t what we want, as we only want the methods defined within the Dog class, without the methods of its ancestors.

To do that, we pass false to instance_methods to only get the methods defined within the Dog class:

Dog.instance_methods(false)

=> []

We can conclude that Ruby uses something similar to:

Dog.instance_methods(false).include?(:speak)

=> false

Now that we know the Dog class doesn’t define the #speak method, we can go one class up in the ancestor chain to the Animal class.

Dog.ancestors

=> [Dog, Animal, Object, Kernel, BasicObject]

It proceeds to the Animal class, where it finds the holy grail.

Animal.instance_methods(false)

=> [:speak]

The algorithm is straightforward: