Saturday, October 1, 2011

Playing with ruby modules


Its time to play around with ruby modules as its a weekend. I always wanted to check how do ruby modules solves multiple inheritance problem. So lets not waste time, here it goes:



module M1

def add(x, y)
x + y
end

end

module M2

def add(x, y)
(x * x) + (y * y)
end

end

class A
include M1, M2
end

a = A.new
puts "Addition is: #{a.add(2,3)}"
puts A.ancestors

Result:
Addition is: 5
A
M1
M2
Object
Kernel


So what I have done over here is that I have included 2 modules in a class "A" and both the modules "M1" and "M2" have the "add" method. When I create an object of "A" and call "add" method, "M1's add" got executed. To confirm that "M2" is included in class "A", I also made a call to "A.ancestors".



Whats going on?

Any module gets injected as a direct superclass of whoever includes it, as mentioned over here: http://mousebender.wordpress.com/2007/11/18/including-a-module-in-ruby/. But again in which order? To figure out that, I read this: http://www.ruby-doc.org/core/classes/Module.src/M000438.html.


After reading about how does include works, I changed the code:

module M1

def M1.append_features(mod)
puts "append_features of M1"
end

def add(x, y)
x + y
end

end

module M2

def M2.append_features(mod)
puts "append_features of M2"
end

def add(x, y)
(x * x) + (y * y)
end
end

class A
include M1, M2
end

a = A.new
puts "Addition is: #{a.add(2,3)}"
puts A.ancestors

result:
append_features of M2
append_features of M1
NoMethodError: undefined method `add' for #
A
Object
Kernel


After implementing append_features method its clear that in which order modules get included. Obviously a.add is now failing because that method didn't got injected in the class "A". As one can see the result of a.ancestors, no M1 and M2 in the output. Lets remove the append_features implementation, now runtime will check "add" method first in class "A" if not found it will check in the immediate ancestor which is M1 and it will find it and M1.add will be executed.


Enjoy Ruby