Multiple Inheritance in Ruby

16 Jan 2009 – Miami, FL

I’m in Miami for a couple of days on business and spent the plane journey reading up on Ruby Mixins and how it gets around the multiple inheritance problem.

Coming from a Java background, where there was no multiple inheritance (technically there isn’t any in Ruby either), the solution to this one was pretty interesting to me. Ruby uses the concept of a Mixin which is really just a module. A module can’t be instantiated and is just a set of functionality.

 
	?> module Mixin
	>> def mixin_method
	>> "Mixin method"
	>> end
	>> end
	=> nil
	>> 
	?> class A
	>> include Mixin
	>> end
	=> A
	>> 
	?> a = A.new
	>> a.mixin_method
	=> "Mixin method"

Where it gets interesting (and the reason Java never supported multiple inheritance) is what to do if we have conflicting methods in our superclasses (“Diamond Problem” anyone ?). Technically, Ruby does not support multiple inheritance, but you can mixin multiple modules into other classes or modules. How does Ruby deal with the diamond problem ? Well it basically uses the last method to be included. You can see below, that the returned method is based on the last one to be introduced to the lookup chain.

 
	?> module MixinA
	>> def hello
	>> "hello from A"
	>> end
	>> end
	=> nil
	>> 
	?> module MixinB
	>> def hello
	>> "hello from B"
	>> end
	>> end
	=> nil
	>> 
	?> class C
	>> include MixinA
	>> include MixinB
	>> end
	=> C
	>> 
	?> c = C.new
	=> #<C:0x5e6550>
	>> c.hello
	=> "hello from B"
	>> 
	?> class D
	>> include MixinB
	>> include MixinA
	>> end
	=> D
	>> 
	?> d = D.new
	=> #<D:0x5e0ca4>
	>> d.hello
	=> "hello from A"

And thats it. You can also include a module in another module, just like normal inheritance. Module is actually a super-class of Class, but classes cannot be mixed-in to other classes, only Modules can.

 
	>> module MixinA
	>> def hello
	>> "hello"
	>> end
	>> end
	=> nil
	>> 
	?> module MixinB
	>> include MixinA
	>> def hello2
	>> "hello2"
	>> end
	>> end
	=> nil
	>> 
	?> class C
	>> include MixinB
	>> end
	=> C
	>> 
	?> c = C.new
	=> #<C:0x5e7608>
	>> c.hello
	=> "hello"
	>> c.hello2
	=> "hello2"

For a more complete introduction, of course you can simply `ri Module`.