The Case for Multiple-Inheritance

T

Trans

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

Austin Ziegler

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
 
M

MenTaLguY

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
 
J

Joel VanderWerf

MenTaLguY said:
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.)
 
M

MenTaLguY

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
 
T

Trans

Hi Austin,

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

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.
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?
That's fine, but nothing you've written suggests that MI is a good idea.


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.
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'm sending it back. It's overcooked and watery.

LOL.

That's because it's stew not potatoes ;)

T.
 
R

Rudi Cilibrasi

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

Eric Hodel

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

Austin Ziegler

It's been a while. Glad to see your still ready to go a round :)
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.
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.
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
 
M

Michael T. Richter

--=-JJ2uY/1lcl2eOzCCFUfG
Content-Type: multipart/alternative; boundary="=-24/9nLeEDLiKmCRYoFTA"


--=-24/9nLeEDLiKmCRYoFTA
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

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

--=20
Michael T. Richter <[email protected]> (GoogleTalk:
(e-mail address removed))
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)

--=-24/9nLeEDLiKmCRYoFTA
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
<META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
</HEAD>
<BODY>
On Sat, 2007-06-10 at 07:13 +0900, Austin Ziegler wrote:
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">Avoid inheritance when you don't need it -- and you=
need it a lot less</FONT>
<FONT COLOR=3D"#000000">than you think. Composition is usually a better app=
roach than</FONT>
<FONT COLOR=3D"#000000">inheritance.</FONT>
</PRE>
</BLOCKQUOTE>
<BR>
This is the big thing about OOP that I don't like: the &quot;golden hammer&=
quot; solution of making everything a class and using inheritance as the be=
-all, end-all of construction.<BR>
<BR>
Inheritance makes things fragile, not robust.&nbsp; It interferes with re-u=
sability in most circumstances instead of enhancing it.&nbsp; Why is it suc=
h a popular technique?!<BR>
<BR>
<TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
<TR>
<TD>
-- <BR>
<B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:[email protected]">ttmri=
(e-mail address removed)</A>&gt; (<B>GoogleTalk:</B> (e-mail address removed))<BR>
<I>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 i=
s to make it so complicated that there are no obvious deficiencies. (Charle=
s Hoare)</I>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

--=-24/9nLeEDLiKmCRYoFTA--

--=-JJ2uY/1lcl2eOzCCFUfG
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iD8DBQBHBtijLqyWkKVQ54QRAvlCAJ97TWf3BAb+yrbWQYi9Ku+4mL5ORgCeMBXg
K7GZCzOwl25cBLErJtu/ENI=
=5C05
-----END PGP SIGNATURE-----

--=-JJ2uY/1lcl2eOzCCFUfG--
 
M

Michael T. Richter

--=-KsW0G4xOpuM1Wi7RJj69
Content-Type: multipart/alternative; boundary="=-W+d/wcyIfoDcraZHToqk"


--=-W+d/wcyIfoDcraZHToqk
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

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

--=20
Michael T. Richter <[email protected]> (GoogleTalk:
(e-mail address removed))
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)

--=-W+d/wcyIfoDcraZHToqk
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
<META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
</HEAD>
<BODY>
On Sat, 2007-06-10 at 08:02 +0900, Trans wrote:
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">&gt; Avoid inheritance when you don't need it -- an=
d you need it a lot less</FONT>
<FONT COLOR=3D"#000000">&gt; than you think. Composition is usually a bette=
r approach than</FONT>
<FONT COLOR=3D"#000000">&gt; inheritance.</FONT>
</PRE>
</BLOCKQUOTE>
<PRE>

</PRE>
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">What this point of having inheritance if we're just=
going to avoid it?</FONT>
</PRE>
</BLOCKQUOTE>
<BR>
&quot;I use it because I have it&quot; is <B>not</B> a valid reason for usi=
ng <B>any</B> language feature of <B>any</B> kind.&nbsp; Why do we have the=
plethora of $-variables in Ruby if we're just going to avoid it?&nbsp; Why=
do we have the loop method if we generally don't use it?&nbsp; Why do we h=
ave <B>any</B> language constructs at all beyond 16 basic assembly language=
statements, in fact?<BR>
<BR>
Switch over to cars for a moment.&nbsp; A car mechanic -- a good one, anywa=
y -- will have a <B><I>huge</I></B> chest of tools.&nbsp; Some of those too=
ls only get used perhaps once or twice a year.&nbsp; Why does he have them?=
&nbsp; Because when they're used, they're the single best tool for the job =
and other tools are just not adequate is why.<BR>
<BR>
The features of a programming languages (as well as the set of programming =
languages known) are the &quot;mechanics tools&quot; of the professional pr=
ogrammer.&nbsp; 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).&nbsp; Bu=
t 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 ever=
ything into inheritance trees just because the language you use supports in=
heritance.<BR>
<BR>
Object-oriented programming has at its core objects.&nbsp; Inheritance is j=
ust one tool used for manipulating objects.&nbsp; Composition is another.&n=
bsp; Your question could easily be reworded (and it's a rewording I prefer =
since this is the normal problem in libraries and applications) to: &quot;W=
hat is the point of supporting composition and aggregation if we're just go=
ing to avoid them?&quot;<BR>
<BR>
Branch out.&nbsp; Investigate other ways of constructing programs.&nbsp; Lo=
ok specifically into decoupling of objects if you want a more flexible and =
maintainable approach to building systems.<BR>
<BR>
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">I can use composition in any language. Ruby's an OO=
P. Shouldn't we use</FONT>
<FONT COLOR=3D"#000000">OOP and it's patterns where they apply? Isn't that =
the whole point?</FONT>
</PRE>
</BLOCKQUOTE>
<BR>
Look into the Gang of Four's Design Patterns book sometime.&nbsp; Count the=
patterns that use composition and aggregation over inheritance.&nbsp; And =
read the part that warns against overuse of inheritance....<BR>
<BR>
<TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
<TR>
<TD>
-- <BR>
<B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:[email protected]">ttmri=
(e-mail address removed)</A>&gt; (<B>GoogleTalk:</B> (e-mail address removed))<BR>
<I>We should sell bloat credits, the way the government sells pollution cre=
dits. 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)</I>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

--=-W+d/wcyIfoDcraZHToqk--

--=-KsW0G4xOpuM1Wi7RJj69
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iD8DBQBHBtvVLqyWkKVQ54QRAlaXAKDP+Z14W5ksv82h8bDRoO5qtihqDwCglOlp
EzB/q9kIkRwWRnfEImSO5zU=
=XW7y
-----END PGP SIGNATURE-----

--=-KsW0G4xOpuM1Wi7RJj69--
 
R

Rick DeNatale

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

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


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.

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

Ryan Davis

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

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

While I agree with your following email (=AB"I use it because I have =20
it" is not a valid reason for using any language feature of any =20
kind.=BB) whole-heartedly, I disagree thoroughly with the above claims. =20=

I suggest it is such a popular technique because it disproves your =20
claims more often than not.
 
M

Morton Goldberg

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
 
M

Michael T. Richter

--=-3Ly+Bh5SO73GQiweOmsE
Content-Type: multipart/alternative; boundary="=-nx213ZHHki82TZXAV0Os"


--=-nx213ZHHki82TZXAV0Os
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

While I agree with your following email (=C2=AB"I use it because I have =20
it" is not a valid reason for using any language feature of any =20
kind.=C2=BB) whole-heartedly, I disagree thoroughly with the above claims= =20
I suggest it is such a popular technique because it disproves your =20
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".

--=20
Michael T. Richter <[email protected]> (GoogleTalk:
(e-mail address removed))
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)

--=-nx213ZHHki82TZXAV0Os
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; CHARSET=3DUTF-8">
<META NAME=3D"GENERATOR" CONTENT=3D"GtkHTML/3.12.1">
</HEAD>
<BODY>
On Sat, 2007-06-10 at 10:13 +0900, Ryan Davis wrote:
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">&gt; This is the big thing about OOP that I don't l=
ike: the &quot;golden </FONT>
<FONT COLOR=3D"#000000">&gt; hammer&quot; solution of making everything a c=
lass and using inheritance </FONT>
<FONT COLOR=3D"#000000">&gt; as the be-all, end-all of construction.</FONT>
</PRE>
</BLOCKQUOTE>
<BR>
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">&gt; Inheritance makes things fragile, not robust. =
It interferes with </FONT>
<FONT COLOR=3D"#000000">&gt; re-usability in most circumstances instead of =
enhancing it. Why is </FONT>
<FONT COLOR=3D"#000000">&gt; it such a popular technique?!</FONT>
</PRE>
</BLOCKQUOTE>
<PRE>

</PRE>
<BLOCKQUOTE TYPE=3DCITE>
<PRE>
<FONT COLOR=3D"#000000">While I agree with your following email («&quo=
t;I use it because I have </FONT>
<FONT COLOR=3D"#000000">it&quot; is not a valid reason for using any langua=
ge feature of any </FONT>
<FONT COLOR=3D"#000000">kind.») whole-heartedly, I disagree thoroughly=
with the above claims. </FONT>
<FONT COLOR=3D"#000000">I suggest it is such a popular technique because it=
disproves your </FONT>
<FONT COLOR=3D"#000000">claims more often than not.</FONT>
</PRE>
</BLOCKQUOTE>
<BR>
Do you <B>really</B> mean to be using &quot;proof by popularity&quot;-style=
arguments here?&nbsp; Because if you do, Ruby is a worse programming langu=
age than, say, Python.&nbsp; Or Java.&nbsp; Or C++.&nbsp; Or C.&nbsp; Or CO=
BOL (!).<BR>
<BR>
I have tended to find zero correlation between popularity and quality.&nbsp=
; Between, as the old chestnut goes, &quot;truth&quot; and the &quot;number=
of votaries&quot;.<BR>
<BR>
<TABLE CELLSPACING=3D"0" CELLPADDING=3D"0" WIDTH=3D"100%">
<TR>
<TD>
-- <BR>
<B>Michael T. Richter</B> &lt;<A HREF=3D"mailto:[email protected]">ttmri=
(e-mail address removed)</A>&gt; (<B>GoogleTalk:</B> (e-mail address removed))<BR>
<I>We should sell bloat credits, the way the government sells pollution cre=
dits. 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)</I>
</TD>
</TR>
</TABLE>
</BODY>
</HTML>

--=-nx213ZHHki82TZXAV0Os--

--=-3Ly+Bh5SO73GQiweOmsE
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iD8DBQBHBv+OLqyWkKVQ54QRAuh6AKCJ4riEeJs3PjVtVtPppcGSmdrssQCgyb/8
lb0LIOilyNukvPYGtnqoeaU=
=vuT3
-----END PGP SIGNATURE-----

--=-3Ly+Bh5SO73GQiweOmsE--
 
S

Sylvain Joyeux

I'm all with you on that :p

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
 
S

Sylvain Joyeux

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
 
P

Pat Maddox

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

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

Pat
 
P

Pat Maddox

I'm all with you on that :p

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

It's funny because a lot of people on this list have a hard time
wrapping their head around duck-typing :) 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 :)

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
 
N

Neil Wilson

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,967
Messages
2,570,148
Members
46,694
Latest member
LetaCadwal

Latest Threads

Top