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.

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 10/5/07, Trans <transfire@gmail.com> wrote:
--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

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 06:06:45 +0900, Trans <transfire@gmail.com> 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?

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

To make this issue a bit more concrete, is there ever a time when you'll
have more than one of these objects instantiated in memory and, for example,
a list of Application references where some point to LinuxApplications, some
point to LinuxVideoPlayerApplications, etc.? I suspect you'll only ever have
a LinuxVideoPlayerApplication. In that case, inheritance doesn't solve any
problems. The mixin (module) approach lets you refer to the object
generically as an Application when that makes sense, a Video Player when
that makes sense, etc. without inheritance.

Also, I suspect this hierarchy violates the Liskov Substitution Principle,
which is our most effective definition of what inheritance really means in
software. Is a LinuxVideoPlayerApplication object substitutable everywhere a
LinuxApplication is used? Or, does the former "specialize" the behavior of
the latter in such a way that substitution would break the code expecting a
LinuxApplication? This is very common in "deep" class hierarchies. The idea
that subclasses "specialize" the behavior of superclasses has to considered
carefully.

···

On 10/5/07, Trans <transfire@gmail.com> wrote:

...
  class VideoPlayerApplication < Application

  class LinuxApplication < Applicaiton

Oh no!

  class LinuxVideoPlayerApplication < VideoPlayerApplication

or

  class LinuxVideoPlayerApplication < LinuxApplication

--
Dean Wampler
http://www.objectmentor.com
http://www.aspectprogramming.com
http://aquarium.rubyforge.org
http://www.contract4j.org

MenTaLguY 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.)

···

On Sat, 6 Oct 2007 06:06:45 +0900, Trans <transfire@gmail.com> wrote:

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Hi Austin,

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

> 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++.

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.

> 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?

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?

> 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.

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.

···

On Oct 5, 3:13 pm, "Austin Ziegler" <halosta...@gmail.com> wrote:

On 10/5/07, Trans <transf...@gmail.com> 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?!

···

On Sat, 2007-06-10 at 07:13 +0900, Austin Ziegler 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.

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
There are two ways of constructing a software design. One way is to make
it so simple that there are obviously no deficiencies. And the other way
is to make it so complicated that there are no obvious deficiencies.
(Charles Hoare)

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

···

On 10/5/07, Sylvain Joyeux <sylvain.joyeux@polytechnique.org> wrote:

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

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 Oct 6, 7:45 am, Sylvain Joyeux <sylvain.joy...@polytechnique.org> 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.

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

IMHO MI doesn't necessarily imply that every class goes well with
every other class and it's up to the developer to handle name clashes
and the like the same way developers have to make sure they don't, eg,
add a number and a hash. Languages like eiffel provide facilities to
rename methods for this.

While I agree that Ruby's modules/mixins can handle well many
situations where one would rely on MI eg in Eiffel and also that MI is
likely to unnecessarily increase the code's complexity to a degree of
unmaintainability, I can still remeber a (very) few situations when it
would have been handy. Eg with mixins, AFAIK you can't include class
methods and object methods at the same time, can you? Maybe I'm wrong
in this respect.

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

···

On Sat, 6 Oct 2007 07:25:13 +0900, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:

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

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 10/5/07, Trans <transfire@gmail.com> wrote:

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 Ziegler" <halosta...@gmail.com> wrote:
> On 10/5/07, Trans <transf...@gmail.com> 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++.

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.

> > 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?

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?

> > 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.

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.

--
"We can try to do it by breaking free of the mental prison of
separation and exclusion and see the world in its interconnectedness
and non-separability, allowing new alternatives to emerge." -- after
Vandana Shiva

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 Oct 5, 2007, at 16:02 , Trans wrote:

--
Poor workers blame their tools. Good workers build better tools. The
best workers get their tools to do the work for them. -- Syndicate Wars

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

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++.

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.

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.

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.

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.

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.

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 10/5/07, Trans <transfire@gmail.com> wrote:

On Oct 5, 3:13 pm, "Austin Ziegler" <halosta...@gmail.com> wrote:

On 10/5/07, Trans <transf...@gmail.com> wrote:

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

> 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 Sat, 2007-06-10 at 08:02 +0900, Trans wrote:

--
Michael T. Richter <ttmrichter@gmail.com> (GoogleTalk:
ttmrichter@gmail.com)
We should sell bloat credits, the way the government sells pollution
credits. Everybody's assigned a certain amount of bloat, and if they go
over, they have to purchase bloat credits from some other group that's
been more careful. (Bent Hagemark)

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 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?!

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

···

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

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

It's funny because a lot of people on this list have a hard time
wrapping their head around duck-typing :slight_smile:

I wouldn't say they have a hard time of wrapping their head around it

···

--
although I find this metaphor quite interesting. Maybe they rather
think
of duck-typing as informal interfaces, but let's not call it this way
and give it a funky name instead, without having the benefits of
typing/formal interfaces.

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.

I'd be very interested how you'd argue against MI from your point of
view?

I suppose not directly, but it's a standard idiom to make use of
Ruby's Module#included callback and extend the receiver with another
module named ClassMethods:
http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html

Pat

···

On 10/6/07, tho_mica_l <micathom@gmail.com> wrote:

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

Eg with mixins, AFAIK you can't include class
methods and object methods at the same time, can you? Maybe I'm wrong
in this respect.