zwiebl zwiebl - 4 months ago 27
Ruby Question

inheritance from multiple modules?

I understand that when a module is included into a class, it behaves like a direct superclass of the class it is included into.

However, what if there are multiple modules included in the same class? Which one is now a direct superclass if there is no relationship between modules?

And what if module A includes module B (so there is a relationship in a way), overrides some of its methods, and now both A and B are included in the same class. Does that class now define all methods from A and B, and from the methods that are common to A and B, it uses only the methods that A overrides?

ndn ndn

To help you understand that, ruby provides you with Module#ancestors:

Object.ancestors # => [Object, Kernel, BasicObject]

This is the order, in which an instance method of Object will be searched for. So lets test your examples.

First, two modules included:

module M; end
module N; end
class C
  include M
  include N

C.ancestors # => [C, N, M, Object, Kernel, BasicObject]

So the methods will first be searched for in C. If a method with the given name is not found, it is searched for first in N and then in M. In other words - the reverse order of which you included the modules.

Second, module, including a module, included in a class:

module X; end
module Y
  include X
class K
  include Y

K.ancestors # => [K, Y, X, Object, Kernel, BasicObject]

So we can see that the same rule applies for including in modules. Just as in the previous example a method will first be searched for in C and only then in the modules included in C, here a method will first will be searched for in a module, and only then in the included modules in that module.

The reason for that, other than consistency, is that classes are actually modules in Ruby:

Class.superclass # => Module

There are a lot of rules. For example including the same module twice in the hierarchy, singleton classes, #prepend, #method_missing and so on. But you can deduce all of it knowing how to use #ancestors.