The Case for Multiple-Inheritance

So I working on little lib that’s ripe for an adapter pattern, when I
see quite clearly that I have a bit of a dilemma. I have two clear
inheritance hierarchies converging. I want to create a
LinuxVideoPlayerApplication subclass, but it needs to inherit from
both VideoPlayerApplication and LinuxApplication.

class VideoPlayerApplication < Application

class LinuxApplication < Applicaiton

Oh no!

class LinuxVideoPlayerApplication < VideoPlayerApplication

or

class LinuxVideoPlayerApplication < LinuxApplication

Ruby forces me make a choice. Which is “more real” I guess is it’s
demand. But the choice is contrived. Both apply, and Ruby’s strict
single-inheritance philosophy does nothing for me in the end except
make my life more complicated. One way or the other I am going to get
both behaviors in there. Period.

So as things are, I’m stuck with making one of them a module instead
of a class. But then I loose metaclass inheritance, which can be a
real pain sometimes. I become inclined to make them both modules and
use separate meta-modules if need be, to keep things nicely symmetric.
But really, why should I have to make such a fuss? Why do I have to
draw so many abstract distinctions when there is no such thing in my
actual model?

I think it would be a good idea to really give some deep consideration
as to why modules and classes are distinct in Ruby. It’s clear from
Ruby’s source that the distinction is self-inflicted to begin with.
Why? Are we really gaining anything by the distinction, or are we just
making things harder for ourselves w/o necessarily realizing it,
simply because that’s the “philosophy”.

Food for thought,
T.

On 10/5/07, Trans [email protected] wrote:

So I working on little lib that’s ripe for an adapter pattern, when I
see quite clearly that I have a bit of a dilemma. I have two clear
inheritance hierarchies converging. I want to create a
LinuxVideoPlayerApplication subclass, but it needs to inherit from
both VideoPlayerApplication and LinuxApplication.

I think that you’ve got a problem here, and it won’t be solved with MI.
You need to reapproach the issue. I have yet to find a time when MI
makes sense even in C++.

class VideoPlayerApplication < Application
class LinuxApplication < Application

Oh no!

class LinuxVideoPlayerApplication < VideoPlayerApplication
or
class LinuxVideoPlayerApplication < LinuxApplication

Frankly, I don’t think you’ve got a good design here, without seeing
anything else.

A LinuxApplication isn’t sensible. What makes a LinuxApplication
different from a GenericApplication or from a WindowsApplication? In
other words, I think that you’ve set yourself up for the dichotomy by
not considering this the right way.

Think of it in terms of aspects. What are the aspects that make an
application a Linux application? How can you pull those in cleanly?

Ruby forces me make a choice. Which is “more real” I guess is it’s
demand. But the choice is contrived. Both apply, and Ruby’s strict
single-inheritance philosophy does nothing for me in the end except
make my life more complicated. One way or the other I am going to get
both behaviors in there. Period.

That’s fine, but nothing you’ve written suggests that MI is a good idea.

So as things are, I’m stuck with making one of them a module instead
of a class.

Why?

Avoid inheritance when you don’t need it – and you need it a lot less
than you think. Composition is usually a better approach than
inheritance.

But then I loose metaclass inheritance, which can be a
real pain sometimes. I become inclined to make them both modules and
use separate meta-modules if need be, to keep things nicely symmetric.
But really, why should I have to make such a fuss? Why do I have to
draw so many abstract distinctions when there is no such thing in my
actual model?

Why are you choosing to implement this in perhaps the worst OO way
possible? Why have you made metaclass inheritance important? Again:
consider composition.

I think it would be a good idea to really give some deep consideration
as to why modules and classes are distinct in Ruby. It’s clear from
Ruby’s source that the distinction is self-inflicted to begin with.
Why? Are we really gaining anything by the distinction, or are we just
making things harder for ourselves w/o necessarily realizing it,
simply because that’s the “philosophy”.

Food for thought,

I’m sending it back. It’s overcooked and watery.

-austin

On Sat, 6 Oct 2007 06:06:45 +0900, Trans [email protected] wrote:

I think it would be a good idea to really give some deep consideration
as to why modules and classes are distinct in Ruby. Why?

One reason is to avoid ambiguity about object representations. Let’s
say that instance methods of class A assume one representation, and the
instance methods of class B assume another, incompatible, representation
[1].

class C < A, B
end

Should A’s methods or B’s methods break when called on an instance of
C?

One solution I can think of immediately would be for a newly allocated
instance of C to allocate an instance of A and an instance of B behind
the scenes, delegating method calls to them as appropriate.

However, at that point it’s starting to sound suspiciously like
aggregation… have you considered using aggregation rather than just
inheritance for modeling your problem?

-mental

[1] In Ruby 1.8, representations can be incompatible because they either
used instance variables with conflicting names, or because they are
of different RBasic types – e.g. T_STRUCT versus T_DATA

On Sat, 6 Oct 2007 07:25:13 +0900, Joel VanderWerf
[email protected] wrote:

Isn’t ivar conflict an argument against mixins just as much as it is an
argument against MI?

Yes, although I don’t think it’s as strong an argument as differing
RBasic
types. Well-designed mixins can usually (not always) avoid using
instance
variables, and the possibility of conflict can be greatly reduced, if
you
give the instance variables meaningful suffixes.

That isn’t to say that I’ve never experienced an ivar conflict,
though…

-mental

Hi Austin,

It’s been a while. Glad to see your still ready to go a round :slight_smile:

On Oct 5, 3:13 pm, “Austin Z.” [email protected] wrote:

makes sense even in C++.
Huh. Seems to me whatever you call it, that’s exactly how it is going
to end up. I’ve encapsulated two different behaviors and they are
going to end in one place --i.e. multiple inheritance. Whether I
implement it via classes, modules, composition or even code injection,
the formal result is the same. That’s really the crux of my argument.

anything else.

A LinuxApplication isn’t sensible. What makes a LinuxApplication
different from a GenericApplication or from a WindowsApplication? In
other words, I think that you’ve set yourself up for the dichotomy by
not considering this the right way.

Think of it in terms of aspects. What are the aspects that make an
application a Linux application? How can you pull those in cleanly?

Why do you think it is not sensible? I would say, a LinuxApplication
has a different null device method for instance, just to pick
something out the blue. Do you think it isn’t sensible b/c a
LinuxApplication isn’t something to be initialized --that it is just a
base class? But then the VideoPlayerApplication class isn’t sensible
either for the same reason. Neither is useful until they come
together. Or is it not sensible b/c a LinuxApplication is something
more general than a VideoPlayerApplication? Well, that’s a fair
argument for making the LinuxApplication the module of the two. But
still that’s just a matter of degree not of completely different
character. Or is it not sensible for some other reason?

Why?

Avoid inheritance when you don’t need it – and you need it a lot less
than you think. Composition is usually a better approach than
inheritance.

What this point of having inheritance if we’re just going to avoid it?
I can use composition in any language. Ruby’s an OOP. Shouldn’t we use
OOP and it’s patterns where they apply? Isn’t that the whole point?
Plus composition is generally slower. On an already slow language like
Ruby that kind of stinks.

But then I loose metaclass inheritance, which can be a
real pain sometimes. I become inclined to make them both modules and
use separate meta-modules if need be, to keep things nicely symmetric.
But really, why should I have to make such a fuss? Why do I have to
draw so many abstract distinctions when there is no such thing in my
actual model?

Why are you choosing to implement this in perhaps the worst OO way
possible? Why have you made metaclass inheritance important? Again:
consider composition.

How is it the worse OO way possible? What you are advocating is not
OOP at all. Don’t get me wrong. I have nothing against composition,
but I’m surprised you would suggest it in an OOP language to model
something that has a clear inheritance structure.

I think it would be a good idea to really give some deep consideration
as to why modules and classes are distinct in Ruby. It’s clear from
Ruby’s source that the distinction is self-inflicted to begin with.
Why? Are we really gaining anything by the distinction, or are we just
making things harder for ourselves w/o necessarily realizing it,
simply because that’s the “philosophy”.

Food for thought,

I’m sending it back. It’s overcooked and watery.

LOL.

That’s because it’s stew not potatoes :wink:

T.

MenTaLguY wrote:

On Sat, 6 Oct 2007 06:06:45 +0900, Trans [email protected] wrote:

I think it would be a good idea to really give some deep consideration
as to why modules and classes are distinct in Ruby. Why?

One reason is to avoid ambiguity about object representations. Let’s
say that instance methods of class A assume one representation, and the
instance methods of class B assume another, incompatible, representation
[1].

[1] In Ruby 1.8, representations can be incompatible because they either
used instance variables with conflicting names, or because they are
of different RBasic types – e.g. T_STRUCT versus T_DATA

Isn’t ivar conflict an argument against mixins just as much as it is an
argument against MI?

Solutions to this have been discussed…

T_STRUCT vs T_DATA is still a problem for MI, of course. (As is T_DATA
vs T_DATA when the underlying C types are different.)

I agree with Austin. And here’s a good explanation as to why:

http://brighton.ncsa.uiuc.edu/prajlich/T/node14.html

I can use composition in any language. Ruby’s an OOP. Shouldn’t we use
OOP and it’s patterns where they apply? Isn’t that the whole point?

In summary: inheritance is “white-box reuse” and composition is
“black-box reuse”. There are strong arguments that essentially point
out that inheritance is a tighter coupling of parts and less
encapsulated in terms of abstraction than composition, which also
happens to be my favorite of the two.

Cheers,

-r.

On Oct 5, 2007, at 16:02 , Trans wrote:

What this point of having inheritance if we’re just going to avoid it?
I can use composition in any language. Ruby’s an OOP. Shouldn’t we use
OOP and it’s patterns where they apply? Isn’t that the whole point?

No.

OO features are just another tool to use when you need it (note that
I said need, not want). Just because you can use an eight-pound
sledge for any nail-driving purpose doesn’t mean you should.
Likewise you shouldn’t use complicated OO features when simple
procedural code will suffice.

Keeping things simple benefits everyone, but yourself most
importantly. There’s no reason to construct something so large you
can barely maintain or understand it.

WTF had an excellent post about this, including this quote from
Michael A. Jackson’s Principles of Program Design:

Programmers […] often take refuge in an understandable, but
disastrous, inclination towards complexity and ingenuity in their
work. Forbidden to design anything larger than a program, they
respond by making that program intricate enough to challenge their
professional skill.

http://worsethanfailure.com/Comments/The-Mythical-Business-Layer.aspx

Instead of starting with objects, you should start with a method,
then add another. Objects will spring out of it naturally as you
refactor for reuse.

Attempting to determine your objects before writing any methods is
like performing surgery with meat-hooks and salad tongs. It can be
done, but most of the time you’ll end up with a sloppy, sagging mess.

On 10/5/07, Trans [email protected] wrote:

It’s been a while. Glad to see your still ready to go a round :slight_smile:

Huh. Seems to me whatever you call it, that’s exactly how it is going
to end up. I’ve encapsulated two different behaviors and they are
going to end in one place --i.e. multiple inheritance. Whether I
implement it via classes, modules, composition or even code injection,
the formal result is the same. That’s really the crux of my argument.

The problem with your argument is that it isn’t actually based on
something correct. Composition isn’t at all related to MI, although
delegation can fake it out pretty well, and with fewer problems (since
you’re managing your delegation directly).

What you have is not a LinuxVideoPlayerAppllication but an Application
for Linux with VideoPlayer capabilities (this actually implies a lot
more than just what’s written, but I’ll leave it as that for now).

It’s a bit harder to talk about the design because, as I said, it’s
unclear what a LinuxApplication has that’s separate from a generic
Application or why inheritance (of any sort) is the way to model that.

Plus composition is generally slower. On an already slow language like
Ruby that kind of stinks.

There’s nothing inherently slower about composition. You should use an
inheritance model when you can clearly say that something IS-A rather
than HAS-A. Let’s consider:

A Video Player Application on Linux

Right? Well, it IS an Application. It HAS Linux support and HAS the
ability to play Video. One can break down Video support several ways,
too (and probably should). A video player has something that reads the
file (Reader), passes it through a (polymorphic with inheritance) Codec,
and then takes the Audio and Video streams and sends them to a
SoundPlayer and DisplayBuffer, that may or may not actually be visible
on screen.

Inheritance is important and powerful, but should only be used to
represent things that are essentially interchangeable. Otherwise,
composition is better.

OOP at all. Don’t get me wrong. I have nothing against composition,
but I’m surprised you would suggest it in an OOP language to model
something that has a clear inheritance structure.

But it doesn’t have a clear inheritance structure. It’s a contrived
inheritance structure. Do you consider JavaScript an OO language? You
should, because it is. It also doesn’t have inheritance by default. (It
can be added, but it’s not there by default.)

Like I said, I have yet to see where MI is better than composition and
delegation.

-austin

On Sat, 2007-06-10 at 07:13 +0900, Austin Z. wrote:

Avoid inheritance when you don’t need it – and you need it a lot less
than you think. Composition is usually a better approach than
inheritance.

This is the big thing about OOP that I don’t like: the “golden hammer”
solution of making everything a class and using inheritance as the
be-all, end-all of construction.

Inheritance makes things fragile, not robust. It interferes with
re-usability in most circumstances instead of enhancing it. Why is it
such a popular technique?!

On Sat, 2007-06-10 at 08:02 +0900, Trans wrote:

Avoid inheritance when you don’t need it – and you need it a lot less
than you think. Composition is usually a better approach than
inheritance.

What this point of having inheritance if we’re just going to avoid it?

“I use it because I have it” is not a valid reason for using any
language feature of any kind. Why do we have the plethora of
$-variables in Ruby if we’re just going to avoid it? Why do we have the
loop method if we generally don’t use it? Why do we have any language
constructs at all beyond 16 basic assembly language statements, in fact?

Switch over to cars for a moment. A car mechanic – a good one, anyway
– will have a huge chest of tools. Some of those tools only get used
perhaps once or twice a year. Why does he have them? Because when
they’re used, they’re the single best tool for the job and other tools
are just not adequate is why.

The features of a programming languages (as well as the set of
programming languages known) are the “mechanics tools” of the
professional programmer. If you’re a decent programmer, you have quite
a few of them (much like a decent mechanic has quite a few tools in his
chest). But just like a decent mechanic doesn’t randomly do brake
adjustments because he happens to have a set of brake calipers, you
shouldn’t be stuffing everything into inheritance trees just because the
language you use supports inheritance.

Object-oriented programming has at its core objects. Inheritance is
just one tool used for manipulating objects. Composition is another.
Your question could easily be reworded (and it’s a rewording I prefer
since this is the normal problem in libraries and applications) to:
“What is the point of supporting composition and aggregation if we’re
just going to avoid them?”

Branch out. Investigate other ways of constructing programs. Look
specifically into decoupling of objects if you want a more flexible and
maintainable approach to building systems.

I can use composition in any language. Ruby’s an OOP. Shouldn’t we use
OOP and it’s patterns where they apply? Isn’t that the whole point?

Look into the Gang of Four’s Design Patterns book sometime. Count the
patterns that use composition and aggregation over inheritance. And
read the part that warns against overuse of inheritance…

On 10/5/07, Rudi C. [email protected] wrote:

encapsulated in terms of abstraction than composition, which also
happens to be my favorite of the two.

One should also realize the effect of the different meaning of
inheritance in languages like C++ and languages like Ruby.

In statically typed languages like C++ inheritance is first and
foremost a mechanism for categorizing and constructing types, where as
in Ruby its a mechanism for reusing implementation. The user of an
object in Ruby is unaffected by whether or not that object obtained
it’s capabilities via implementation inheritance or independent
implementation of the required methods.

C++ like languages treat classes like cookie cutters and users of
object rely on all of the cookies coming out of a particular cookie
cutter to have a particular shape, and for sub-cookie cutters to leave
the basic shape unchanged and just add a bump to it. In other words,
both methods and users have intimate knowledge (which many
implementations rely on) of the layout of objects and how that layout
is affected by inheritance.

Dynamically typed oo languages hide the actual shape of the cookie
from the user of the cookie.

And among the dynamically typed languages, Ruby is one of the most
dynamically typed. For example in Smalltalk, methods know about the
shape of the cookie in the sense that the compiler knows that instance
variable x is at offset y from the beginning of every instance which a
method is attached to (whether the instance is actually an instance of
a subclass or not). In Ruby instance variables are dynamically
resolved via a hash, and all instances of a particular class don’t
even have to have all of the instance variables mentioned in methods
of the class at any given time.

Because of this, many of the things which “have to be true” in a
language like C++, or to a slightly lesser extent Java, are irrelevant
in dynamic languages like Smalltalk, and to a greater extent in Ruby.
And it also means that what’s a white box in a language is actually
considerably darker, even if not completely black in a language like
Ruby.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

On Oct 5, 2007, at 17:37 , Michael T. Richter wrote:

This is the big thing about OOP that I don’t like: the “golden
hammer” solution of making everything a class and using inheritance
as the be-all, end-all of construction.

Inheritance makes things fragile, not robust. It interferes with
re-usability in most circumstances instead of enhancing it. Why is
it such a popular technique?!

While I agree with your following email («“I use it because I have
it” is not a valid reason for using any language feature of any
kind.») whole-heartedly, I disagree thoroughly with the above claims.
I suggest it is such a popular technique because it disproves your
claims more often than not.

On Oct 5, 2007, at 7:02 PM, Trans wrote:

What this point of having inheritance if we’re just going to avoid it?

Maybe the point, given Ruby’s modules and single inheritance, is that
each different subclass can mix-in a different module set.

module X
end

module Y
end

class A
end

class AX
include X
end

class AY
include Y
end

class AXY
include X
include Y
end

where
X = Linux
Y = VideoPlayer
A = Application

I don’t know that you can actually re-structure your code in this
way, but if you can, wouldn’t it be more in tune with Ruby’s
strengths than the class structure you are trying to impose?

Regards, Morton

I’m all with you on that :stuck_out_tongue:

People on this list tend to think only as “duck typing”: don’t care
about
the actual class of an object as long as the object responds as it
should.

In my work, I need to reason about the types of my objects. They are
not
instances, they are instances of classes (=models) and I need to reason
about those models. As soon as you’re thinking that way, you have to
have multiple inheritance because single inheritance is not enough.

For now, I’m stuck with using modules to emulate some kind of multiple
inheritance. It sucks.

Sylvain

Yes, although I don’t think it’s as strong an argument as differing
RBasic types. Well-designed mixins can usually (not always) avoid using
instance variables, and the possibility of conflict can be greatly
reduced, if you give the instance variables meaningful suffixes.
Yes. You have to think, when writing mixins, in the context of all
other
mixins they will have to interact with
. Mmmmmm … looks like MI
problem
to me.

Sylvain

On Sat, 2007-06-10 at 10:13 +0900, Ryan D. wrote:

This is the big thing about OOP that I don’t like: the “golden
hammer” solution of making everything a class and using inheritance
as the be-all, end-all of construction.

Inheritance makes things fragile, not robust. It interferes with
re-usability in most circumstances instead of enhancing it. Why is
it such a popular technique?!

While I agree with your following email («“I use it because I have
it” is not a valid reason for using any language feature of any
kind.») whole-heartedly, I disagree thoroughly with the above claims.
I suggest it is such a popular technique because it disproves your
claims more often than not.

Do you really mean to be using “proof by popularity”-style arguments
here? Because if you do, Ruby is a worse programming language than,
say, Python. Or Java. Or C++. Or C. Or COBOL (!).

I have tended to find zero correlation between popularity and quality.
Between, as the old chestnut goes, “truth” and the “number of votaries”.

On 10/5/07, Sylvain J. [email protected] wrote:

I’m probably just being naive here, but what problems does MI solve
that mixins can’t?

Pat

On Oct 6, 7:45 am, Sylvain J. [email protected]
wrote:

In my work, I need to reason about the types of my objects. They are not
instances, they are instances of classes (=models) and I need to reason
about those models. As soon as you’re thinking that way, you have to
have multiple inheritance because single inheritance is not enough.

For now, I’m stuck with using modules to emulate some kind of multiple
inheritance. It sucks.

No, you are stuck in a mindset and you have mapped that mindset onto
classes as though they are the only modelling tool available. There
are lots of other ways of modelling domains.

Classes in dynamic languages are just a convenient shorthand that
covers the general case very well. To be honest you could dump the
abstraction but it would mean more keyboard work.

You might want to consider whether using sets or states may be a
better way of modelling your domain. If you think a network is the
only model that will work, then you might want to brush up on your
graph theory and see if an edge/vector abstraction is suitable.
Clearly a simple tree isn’t suitable (which is what a Class strcture
is).

First choose the correct data structure. If you find a model hard
always reconsider your data structure. It is very common to get the
wrong one, or try and shoehorn a model into the ones you are more
familiar with than learn how to use new ones.

Get your structure reviewed by a peer and try and keep an open mind.
There is nothing shameful about getting the wrong structure. We all do
it all the time.

NeilW

On 10/5/07, Sylvain J. [email protected] wrote:

For now, I’m stuck with using modules to emulate some kind of multiple
inheritance. It sucks.

Sylvain

It’s funny because a lot of people on this list have a hard time
wrapping their head around duck-typing :slight_smile: Not that it’s hard of
course, but foreign to a lot of people.

I think what you mean is that experienced Rubyists tend to think in
terms of duck-typing. I would say that’s because that’s the Ruby
way
Ruby OOP is all about message passing, and as such an object’s
type is simply the messages it handles. Classes are mostly an
implementation detail, i.e. an easy way to construct objects, as far
as the interpretter is concerned.

Of course I don’t know your specific situation…but it’s a pretty
simple OOP principle that you should avoid performing operations based
on an object’s class, and instead move that behavior to the object
itself. Even Java eschews the use of instanceof :slight_smile:

If “types” are very important to your domain, then I would suggest
they ought to be promoted to a domain-level concept. Classes aren’t
intended to be used in that way, nor do I think they’re the
appropriate level of abstraction.

Pat