Forum: Ruby Support for multiple Inheritance by classes

Posted by Ross Konsolebox (konsolebox)
on 2012-11-03 08:21
Will Ruby ever support multiple inheritance through classes instead of
modules? This is good since it won't need modification of existing
classes, and/or converting them to modules or class-module pairs before
they are inherited by a new subclass with the use of include when we
reuse them.

class StableClassA
  puts :A
end

class StableClassB
  puts :B
end

class Inheritor < A, B # won't work
  puts :A
  puts :B
end

# To make things work:

module StableModuleA
  puts :A
end

class StableClassA
  include StableModuleA
end

module StableModuleB
  puts :B
end

class StableClassB
  include StableModuleB
end

class Inheritor
  include StableModuleA
  include StableModuleB
  puts :I
end
Posted by Arlen Cuss (Guest)
on 2012-11-03 12:57
(Received via mailing list)
I think I can say "no" with a fair amount of confidence.

Single-inheritance is considered a good thing (and MI has many 
pitfalls), too: http://www.artima.com/intv/tuesday2.html
Posted by unknown (Guest)
on 2012-11-03 13:49
(Received via mailing list)
unsubscrev please


2012/11/3 Arlen Cuss <ar@len.me>
Posted by Ross Konsolebox (konsolebox)
on 2012-11-04 12:49
Arlen Cuss wrote in post #1082618:
> I think I can say "no" with a fair amount of confidence.
>
> Single-inheritance is considered a good thing (and MI has many
> pitfalls), too: http://www.artima.com/intv/tuesday2.html

Thanks for the reply. The information is adequate. It's quite 
disappointing though since because of that we tend to use class-module 
pair format just to make class ready for multiple-inheritance by mixins 
through its module; or else we always had to rewrite an existing class 
or transfer its contents to a module or the inheriting class itself 
every time we make use of the features.

I believe MI is not that evil and its potential is the one that's more 
to consider or look upon. Some languages also had their ways with 
dealing with those problems: 
https://en.wikipedia.org/wiki/Multiple_inheritance.

I honestly think that Ruby would have been more enjoyable if it had 
supported pure multiple inheritance.
Posted by Peter Hickman (Guest)
on 2012-11-04 13:26
(Received via mailing list)
Even though other languages handle multiple inheritance without any
problems they each handle it in different ways which can lead to subtle
bugs when moving from one language to another. Some languages have even
changed how they handle multiple inheritance between versions (Python
springs to mind here, multiple inheritance got 'clarified' at one point 
-
or so my memory tells me). There is only one way to do single 
inheritance
and this is a good thing.

Coming from languages that allow for multiple inheritance I must say I 
have
yet to encounter a situation where I have said "this would be so much
easier with multiple inheritance"
Posted by Ross Konsolebox (konsolebox)
on 2012-11-04 14:07
Peter Hickman wrote in post #1082748:
> Even though other languages handle multiple inheritance without any
> problems they each handle it in different ways which can lead to subtle
> bugs when moving from one language to another. Some languages have even
> changed how they handle multiple inheritance between versions (Python
> springs to mind here, multiple inheritance got 'clarified' at one point
> - or so my memory tells me).

Good points but think they're really not that essential, especially if 
it's only about one language and just the use of it.

> There is only one way to do single inheritance and this is a good thing.

Considering the capabilities of multiple inheritance and some situations 
where single inheritance don't apply and needs workarounds - like when 
you make a class that needs to inherits a class from an external library 
but also needs to inherit its natural parent class whereas you had no 
choice but to just include the contents of the natural parent class to 
it - I believe that's not always true.

> Coming from languages that allow for multiple inheritance I must say I
> have yet to encounter a situation where I have said "this would be so much 
easier with multiple inheritance"

Perhaps but please consider the example situations I gave. I doubt that 
solutions could always be done without redundancy either by code or by 
work while not sacrificing consistency among classes and not using 
workarounds.
Posted by Peter Hickman (Guest)
on 2012-11-04 14:23
(Received via mailing list)
Well the example you gave at the head of this thread is pretty 
meaningless.
It is always possible to create a convoluted problem that is hard to
implement in any language. My experience in not finding a need for 
multiple
inheritance comes from writing code that people will pay for. No one has
presented my with a genuine problem (as opposed to a puzzle problem) 
where
single inheritance was inadequate. I'm not saying that they don't exist 
but
as problems go I have yet to encounter one.

YMMV
Posted by Ross Konsolebox (konsolebox)
on 2012-11-04 14:46
Peter Hickman wrote in post #1082753:
> Well the example you gave at the head of this thread is pretty
> meaningless.

Depends on one's principles. Also, perhaps it's all because I just 
wanted to give a brief example. I could give real situation examples but 
I find that unnecessary. Also please try to give attention and not evade 
the details I give at least for the sake of keeping this thread 
discussion shorter.

> It is always possible to create a convoluted problem that is hard to
> implement in any language. My experience in not finding a need for
> multiple  inheritance comes from writing code that people will pay for. No one 
has presented my with a genuine problem (as opposed to a puzzle problem)
> where single inheritance was inadequate.

It's not always about as-long-as-it-works theories. Using workarounds is 
not that bad, probably, but sometimes they're too fixed, too hard to 
apply, or too heavy by size that it could have been easier if one 
feature was available.

It also depends on how you love the design of your craft. Not all 
projects are made for the sake of monetary profit. Not that I'm saying 
it's all about craftiness.

Simplicity though safe doesn't always yield simple results. Sometimes 
due to its limits a more complex output is made.
Posted by Peter Hickman (Guest)
on 2012-11-04 15:50
(Received via mailing list)
Ok then lets return to your puzzle problem. Given the first example that
doesn't work. Well done you wrote some code that is invalid Ruby, guess
what, you can do that in any language even if it has multiple 
inheritance.

Now your second example, why did you write it that way? There is no need
for StableClassA or StableClassB. Throw them away and nothing changes as
Inheritor does not inherit from either of them. Here's the code that 
works
the same, it is written as any Ruby programmer would write it.

module StableModuleA
  puts :A
end

module StableModuleB
  puts :B
end

class Inheritor
  include StableModuleA
  include StableModuleB
  puts :I
end

Notice how it looks like the first (broken) example but with modules not
classes. Notice also how it actually works.

Can you now explain what advantages multiple inheritance is supposed to
have over the code given here?

This is why puzzle problems suck. Just give a real problem that is 
better
solved by multiple inheritance and you will have proven your point.
Posted by Ross Konsolebox (konsolebox)
on 2012-11-04 15:56
Peter Hickman wrote in post #1082761:
> Ok then lets return to your puzzle problem. Given the first example that
> doesn't work. Well done you wrote some code that is invalid Ruby, guess
> what, you can do that in any language even if it has multiple
> inheritance.
Yeah I noticed that I didn't place them in methods and directly used 
puts instructions. It's pretty obvious. So what about it?

> Now your second example, why did you write it that way? There is no need
> for StableClassA or StableClassB. Throw them away and nothing changes as
> Inheritor does not inherit from either of them. Here's the code that
> works
> the same, it is written as any Ruby programmer would write it.

Sigh. I was hoping you had understand the essence of this post already. 
StableClassA and StableClassB is meant to be used as standalone and 
working classes as well. They're not just inherited as virtual, abstract 
or incomplete classes.

> module StableModuleA
>   puts :A
> end
>
> module StableModuleB
>   puts :B
> end
>
> class Inheritor
>   include StableModuleA
>   include StableModuleB
>   puts :I
> end
>
> Notice how it looks like the first (broken) example but with modules not
> classes. Notice also how it actually works.
>
> Can you now explain what advantages multiple inheritance is supposed to
> have over the code given here?
>
> This is why puzzle problems suck. Just give a real problem that is
> better
> solved by multiple inheritance and you will have proven your point.

Try to reconsider things again from my reply which is meant to be 
obvious actually. Turns out you really don't have the idea. I'm guessing 
we'll be going through the details bit by bit before you fully 
understand what I mean.
Posted by Peter Hickman (Guest)
on 2012-11-04 17:16
(Received via mailing list)
On 4 November 2012 14:57, Ross Konsolebox <lists@ruby-forum.com> wrote:

> Turns out you really don't have the idea. I'm guessing
> we'll be going through the details bit by bit before you fully
> understand what I mean.
>
>
Provide working code in the language of your choice that demonstrates a
problem that is better served by multiple inheritance than single
inheritance and you will have proven your point.
Posted by Ross Konsolebox (konsolebox)
on 2012-11-04 17:55
Peter Hickman wrote in post #1082774:
> Provide working code in the language of your choice that demonstrates a
> problem that is better served by multiple inheritance than single
> inheritance and you will have proven your point.

I believe I had explained enough. If it's about examples there are many 
around the web. If one is interested to know more about the advantages 
of having multiple inheritance there certainly are many around the web. 
It's not that I can't prove anything. I already encountered two 
situations twice and both were related to inheriting an external class 
where one of the other parent class was already a working class - that 
which could have solved things simpler and easier if MI was possible.

Come to think of it I could actually give you a summary of those 
classes.

Updater
OneTimeUpdater < Updater
DaemonUpdater < Updater

Then the utility was stable. After some time I decided to port it.

ServiceUpdater < DaemonUpdater, Daemon (External Class)

And this time this was not possible. I now have to decide whether I have 
to merge all codes from Updater to DaemonUpdater to make it work with 
ServiceUpdater or use another Class to Inherit Daemon that would control 
ServiceUpdater which would really be a hassle design-wise. No matter how 
you look at multi-inheritance would be the easiest form. Other 
variations would be just workarounds or redundant forms.

Now please reconsider again if you're going to question if my analogy 
with respect to the matter wasn't really that deep that there could have 
been something I missed for you to question me again. This is also just 
an example. An enough proof of concept as I could see it.
Posted by Peter Hickman (Guest)
on 2012-11-04 20:45
(Received via mailing list)
On 4 November 2012 16:55, Ross Konsolebox <lists@ruby-forum.com> wrote:

> Peter Hickman wrote in post #1082774:
> > Provide working code in the language of your choice that demonstrates a
> > problem that is better served by multiple inheritance than single
> > inheritance and you will have proven your point.
>
> I believe I had explained enough. If it's about examples there are many
> around the web.


I have googled and cannot find an example of a problem that is better
served by multiple inheritance than single inheritance. If you know of 
one
then I would be grateful if you could provide the url.


> If one is interested to know more about the advantages
> of having multiple inheritance there certainly are many around the web.
>

Now you are avoiding the question. I am well aware of the advantages of
multiple inheritance, that is not what I asked. What I asked for was
"a problem that is better served by multiple inheritance than
single inheritance". You have not provided one and therefore any hand
wavy arguments you put forward only serve to convince me that you do not
know of even a single instance.


> It's not that I can't prove anything.


Good, then show me the code.


> Come to think of it I could actually give you a summary of those
> classes.
>
> Updater
> OneTimeUpdater < Updater
> DaemonUpdater < Updater
>
>
Again with the hand waving. Without seeing the code I am unable to see 
how
this could be refactored to make it easily implemented with single
inheritance. Likewise I cannot see how difficult it might be and go "oh
he's right, this would be easier with multiple inheritance".

Of course I could just take you word for it ... never gonna happen
Posted by Yukihiro Matsumoto (Guest)
on 2012-11-04 21:05
(Received via mailing list)
Hi,

In message "Re: Support for multiple Inheritance by classes"
    on Mon, 5 Nov 2012 01:55:36 +0900, Ross Konsolebox 
<lists@ruby-forum.com> writes:

|Updater
|OneTimeUpdater < Updater
|DaemonUpdater < Updater
|
|Then the utility was stable. After some time I decided to port it.
|
|ServiceUpdater < DaemonUpdater, Daemon (External Class)

As a general principles, multiple inheritance can be replaced by
modules+mix-in.

|And this time this was not possible. I now have to decide whether I have
|to merge all codes from Updater to DaemonUpdater to make it work with
|ServiceUpdater or use another Class to Inherit Daemon that would control
|ServiceUpdater which would really be a hassle design-wise. No matter how
|you look at multi-inheritance would be the easiest form. Other
|variations would be just workarounds or redundant forms.

It might be "work around". But you have to pay the price of
inheritance graph complexity and resolving conflicts anyway.
Do you fully understand C3 algorithm that CLOS uses to resolve
multiple inheritance priority order.  I don't.  That's one of the
reason I didn't put multiple inheritance in to Ruby.

So, you have options. a) Use mix-ins, compromising "work around".
b) just go to a language with multiple inheritance.

              matz.
Posted by Tony Arcieri (Guest)
on 2012-11-04 22:29
(Received via mailing list)
On Sun, Nov 4, 2012 at 4:49 AM, Ross Konsolebox 
<lists@ruby-forum.com>wrote:

> Thanks for the reply. The information is adequate. It's quite
> disappointing though since because of that we tend to use class-module
> pair format just to make class ready for multiple-inheritance by mixins
> through its module; or else we always had to rewrite an existing class
> or transfer its contents to a module or the inheriting class itself
> every time we make use of the features.
>

What you're basically saying here is we can get most of the properties 
of
multiple inheritance from mixins. That's good!

MI vs. mixins is a philosophical debate. Mixins are a much simpler, more
easy-to-reason-about model than true multiple inheritance, IMO. MI 
brings
with it all sorts of odd corner cases, such as the Diamond Inheritance
Problem:

http://en.wikipedia.org/wiki/Multiple_inheritance#...

So what you view as a weakness I see as a strength.


> I honestly think that Ruby would have been more enjoyable if it had
> supported pure multiple inheritance.


If you really want a Ruby-like language with multiple inheritance, might 
I
suggest Python?
Posted by Admin Tensor (tensor)
on 2012-11-05 04:44
Tony Arcieri wrote in post #1082793:
> If you really want a Ruby-like language with multiple inheritance, might
> I
> suggest Python?

I haven't used Python for quite a while now.  Python supports multiple
inheritance?  Wow.....

Bill
Posted by Stu (Guest)
on 2012-11-05 10:32
(Received via mailing list)
Multiple Inheritance is the GOTO statement of object oriented
programming -- sort of a caveat emptor to people new to the paradigm
coming from a procedural language background.

Module/mix-in would work as far as conceptually. If it's a daemon, as
the so called example used, a system level service. The paradigm
changes. In UNIX not everything is an object. Formally taught to
sysadmins that everything is a file which really really means
everything is a stream of bytes( i.e. C Programming and system
kernel/shell)... This is why Kernel in ruby is a module and not a
class.

I can't think of one reason why multiple inheritance would be useful
for daemon process. Updating based on changes can be accomplished
through creating wrappers to the signals much the same way rc.d/init.d
is. Inside ruby you have access to message passing much the same as
you would expect from any object oriented language.

Ultimately there is nothing wrong with wanting a feature. Consider it
a challenge to work within the context of the language or hack up your
own dsl. MI is not the panacea that early oops language designers
thought it would be. There most certainly is a better way to deal with
various problems and solutions.

Also it's not a "work around" to use Mix-in Modules as the op
suggested. It's actually the preferred and correct way i.e. the Ruby
way. Hit up a couple non object oriented languages and move data back
and forth there. That is the only way to gain enough insight to know
what is a "work around" vs the concept of "working with". The
limitations are not with the ruby language or interpreter. It's with
the users who superimposes such limitations upon themselves.

For one reason or another this thread reminded me of the Execution In
Kingdom of Nouns

http://steve-yegge.blogspot.com/2006/03/execution-...
Posted by Ross Konsolebox (konsolebox)
on 2012-11-05 12:20
Thank you everyone for giving their attention and thoughts to the 
thread, especially Yukihiro-san. It's truly an honor.

I believe my question has been answered already and discussing 
advantages and disadvantages of multi-inheritance over 
single-inheritance with aid of modules is another thing.

Hearing everyone's thoughts especially the master, I think I would just 
accept and respect Ruby the way it is, save that someday I might make a 
personal extension of it if I'm able, well not really.

Thanks again.

I actually imagined this:

class Ruby
  inherit Multiple
  inherit Inheritance
end

Just my thoughts. Cheers, Ross
Posted by Robert Klemme (robert_k78)
on 2012-11-05 13:34
(Received via mailing list)
On Sun, Nov 4, 2012 at 12:49 PM, Ross Konsolebox 
<lists@ruby-forum.com>wrote:

> or transfer its contents to a module or the inheriting class itself
> every time we make use of the features.
>

If you notice you do this regularly you are probably doing something 
wrong
with regard to Ruby's OOP.  It looks as if you want to carry over your
inheritance scheme from language X (C++, Eiffel...).  If something is an
entity (class) _and_ a set of functionality used in various places 
(module)
at the same time then maybe you do not separate the two clear enough. 
For
example, you might notice that your reported 1:1 relationship between 
class
and module should rather be a 1:4 relationship (i.e. an entity being 
built
from various functionalities).  Or maybe you are using inheritance where
you should rather use composition.  All that could of course be 
discussed
much better with a concrete example of your code... :-)


> I believe MI is not that evil and its potential is the one that's more
> to consider or look upon. Some languages also had their ways with
> dealing with those problems:
> https://en.wikipedia.org/wiki/Multiple_inheritance.
>
> I honestly think that Ruby would have been more enjoyable if it had
> supported pure multiple inheritance.
>

For me absence of class MI does not take anything away from the fun and 
I
can't imagine how it could be more fun with class MI.  I tend to believe
though that inheritance is generally overrated.  For me encapsulation is 
a
much more important concept in OOP than inheritance.

Kind regards

robert
Posted by Bob Hutchison (Guest)
on 2012-11-05 17:13
(Received via mailing list)
Holy smoke! What is going on here?!?

If you have ever used a Ruby module as a mixin then you've used multiple 
inheritance. Period. There's no wiggle room. What is a mixin in Ruby is 
part, only part, of what a general multiple inheritance mechanism 
provides in other languages.

And I'll bet that most of you who have used mixins thought they worked 
out pretty well.

So. You've used multiple inheritance and thought it was a good thing.

WHY the near universal contempt for multiple inheritance? What's up?

Cheers,
Bob
Posted by Marc Heiler (shevegen)
on 2012-11-05 18:44
> If you really want a Ruby-like language with multiple
> inheritance, might I suggest Python?

What I do not understand is why people suggest other languages.

It is not as simple. Python uses so many different ways,
it has a completely different philosophy, so suggesting to
use another language A because you do not like one component
in language B isn't any real improvement.

Via modules in ruby you can get quite close to what multiple
inheritance solves.

There is no need to go to python at all.

Ruby and Python are way too similar in their ecological
niche as well.

There is one thing that is however not looked at much at
all in this discussion - less the distinction between
multiple inheritance vs. module mixins, and much more so
what the distinction class vs. module actually serves.

Because I often feel that the distinction between classes
and modules is much more arbitrary than seems to be reasonable.

You have a class Foo, and you mixin three different modules
into it. That is quite close to what multiple inheritance
does too, just not following the classical subclassing tree.

But why is that behaviour contained within a module? Why
could we not assume that ALL behaviour of every object
resides in an (perhaps invisible) module?

Then we could use classes the same way as modules.

module Foo
end

module Bar
  include Foo
end

vs.

class Foo
end

class Bar < Foo
end

To me this is a distinction in Ruby that I do not really
feel is compelling at all.

I have seen people use

class Foo
  module Bar
  end
end

And I asked them why they did it that way, and they told
me that the toplevel class gives them more features,
namely the ability to do Foo.new, than it would by
using a module. That baffled me when I heard it.

My question thus is:

Why must there be this distinction between classes and
modules in this way?
Posted by Robert Klemme (robert_k78)
on 2012-11-06 22:04
(Received via mailing list)
On Mon, Nov 5, 2012 at 6:44 PM, Marc Heiler <lists@ruby-forum.com> 
wrote:

> There is one thing that is however not looked at much at
> all in this discussion - less the distinction between
> multiple inheritance vs. module mixins, and much more so
> what the distinction class vs. module actually serves.
>
> Because I often feel that the distinction between classes
> and modules is much more arbitrary than seems to be reasonable.
>

The difference between class and module in Ruby is
- classes can be instantiated, modules can't
- classes can be inherited (SI), modules can be included (MI)

Did I miss any?  Other than that both are identical (e.g. both can be 
used
as namespace).  For me the more dramatic difference is actually the 
first
one because despite the differences between SI and MI in Ruby it's just
gradual (i.e. the number of items to inherit from - 1 for classes, n for
modules).

So if we assume for a moment that we agree on the most significant
difference then it follows quite naturally (for me at least) that 
classes
should be used for entities, tangible things while modules should rather 
be
used for capabilities (behavior).  And I believe you can see that
distinction at work in the standard library: there's Array which is a 
list
of objects (entity) and Enumerable which is a set of capabilities.


> But why is that behaviour contained within a module? Why
> could we not assume that ALL behaviour of every object
> resides in an (perhaps invisible) module?
>
> Then we could use classes the same way as modules.
>

I do not understand how this follows from the premise.  If all behavior
would reside in modules than classes would not contain behavior at all.
But then classes and modules could not be used the same way.  What am I
missing here?


> Why must there be this distinction between classes and
> modules in this way?
>

I do not think there is a reason why the distinction "must" be there. 
It's
just what Matz designed the language to be.  I think the distinction I 
was
trying to make above is actually not too unreasonable.  It seems so far 
it
has served the language quite well so far.

Kind regards

robert
Posted by Mohammed Yasin Rahman (Guest)
on 2012-11-07 10:34
(Received via mailing list)
I found this answer quite reasonable from this book: 
http://ruby.learncodethehardway.org/book/ex44.html .

The question of "inheritance vs. composition" comes down to an attempt 
to solve the problem of reusable code. You don't want to have duplicated 
code all over your code, since that's not clean and efficient. 
Inheritance solves this problem by creating a mechanism for you to have 
implied features in base classes. Composition solves this by giving you 
modules and the ability to simply call functions in other classes.

If both solutions solve the problem of reuse, then which one is 
appropriate in which situations? The answer is incredibly subjective, 
but I'll give you my three guidelines for when to do which:

Avoid meta-programming (multiple inheritance) at all costs, as it's too 
complex to be useful reliably. If you're stuck with it, then be prepared 
to spend time finding where everything is coming from.
Use composition to package up code into modules that is used in many 
different unrelated places and situations.
Use inheritance only when there are clearly related reusable pieces of 
code that fit under a single common concept, or if you have to because 
of something you're using.
However, do not be a slave to these rules. The thing to remember about 
object oriented programming is that it is entirely a social convention 
programmers have created to package and share code. Because it's a 
social convention, but one that's codified in Ruby, you may be forced to 
avoid these rules because of the people you work with. In that case, 
find out how they use things and then just adapt to the situation.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.