Multiple Inheritance in Ruby

Multiple Inheritance in Ruby?

I think you are taking the meaning of multiple inheritance in a wrong way. Probably what you have in mind as multiple inheritance is like this:

class A inherits class B
class B inherits class C

If so, then that is wrong. That is not what multiple inheritance is, and Ruby has no problem with that. What multiple inheritance really means is this:

class A inherits class B
class A inherits class C

And you surely cannot do this in Ruby.

Modules and multiple inheritance in ruby on rails?

Ruby does not have multiple inheritance. Ruby has something similar called mixins which can be implemented using Modules.

Mixins are not multiple inheritance, but instead mostly eliminate the need for it.

To answer your question, when you include two modules in a class and both of them has the method with same name (in your case, method a), in that case, a method from the 2nd (the last one) Module will be called.

module A
def a1
puts "I am defined in A"
end

def a2
end
end

module B
def a1
puts "I am defined in B"
end

def b2
end
end

class Sample
include A
include B

def s1
end
end

samp = Sample.new
puts samp.a1
# I am defined in B

Why and How?

When a module M is included in a class C, an anonymous proxy class
⟦M′⟧ (called an include class) is created such that its method table
pointer points to M's method table. (Same for the constant table and
module variables.) ⟦M′⟧'s superclass is set to C's superclass and C's
superclass is set to ⟦M′⟧.

Also, if M includes other modules, the process is applied recursively.

puts Sample.ancestors.inspect
# [Sample, B, A, Object, Kernel, BasicObject]

It becomes more clear when you inspect the ancestors of the Sample class. See the order here. When a method is called, Ruby looks for the method definition first in Sample class itself, but doesn't find it. Then, it looks for the a method in B and it finds it and calls it.

Hope it is clear to you now.

How does ruby support multiple inheritance?

Ruby does not directly have multiple inheritance. Ruby has something similar though: mixins. For example:

module M; end
module N; end

class C
include M
include N
end

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

Note that mixins are not multiple inheritance, but instead mostly eliminate the need for it.

Using multi-level inheritance instead of ruby mixins

Two main reasons:

You can only inherit from one class, but you can mix in as many mixins as you want. This means that inheritance is extremely "expensive" in the sense that if you are forced to use inheritance, you are forced to "use up" 100% of your "inheritance resources".

You can compose mixins any way you want. In your example, I can only get the methods of A, the methods of AB, and the methods of ABC. I can, for example, not get only the methods of B. With mixins, I can compose them in any combination: only A, only B, only C, AB, AC, BC, and ABC. I can also compose them in any order I want: I can have the methods of C override the methods of B or I can have the methods of B override the methods of C.

I can easily imagine an object that is both Enumerable and Comparable. (For example, Strings are Comparable and before Ruby 1.9, they also used to be Enumerable.) In your proposed world, this would only be possible if either Enumerable inherits from Comparable or Comparable inherits from Enumerable. However, this will not work: Numerics are Comparable but not Enumerable, Arrays are Enumerable but not Comparable.

There is also a more philosophical / semantic reason: enumerability and comparability are completely orthogonal concepts, why would you tie them together so closely? Inheritance is one of the closest forms of coupling we have, tying two concepts to closely together that don't actually have anything to do with each other, is just wrong.

multiple inheritance for a model

Ruby doesn't support multiple inheritance. To share functionality between models, you want to use mixins. Check out this article, particularly the section on mixins.

Inherit from multiple controllers.

Multiple inheritance is not supported in Ruby. I think extracting the filters into a module and mixing them in would be the cleanest solution.

See for example:
http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html

Multiple-Inheritance type class inheritance in ruby

This is actually quite simple using Ruby:

module Slugish
attr_accessor :slug
def loud_slug
"#{slug}!"
end
end

class Stringy < String
include Slugish
end

class Hashy < Hash
include Slugish
end

hello = Stringy.new("Hello")
world = Stringy.new("World")

hello.slug = "So slow"
world.slug = "Worldly"

hello.loud_slug #=> "So slow!"
world.loud_slug #=> "Worldly!"

hello.is_a?(Slugish) #=> true
world.is_a?(Slugish) #=> true

"#{hello} #{world}" #=> "Hello World"

stuff = Hashy.new
stuff[:hello] = :world
stuff.slug = "My stuff"
stuff.loud_stug #=> "My stuff!"
stuff.is_a?(Slugish) #=> true


Related Topics



Leave a reply



Submit