
Why inheritance sucks - dchest
http://ducktypo.blogspot.com/2010/08/why-inheritance-sucks.html
======
jknupp
I strongly disagree that "code reuse" is a reason to use inheritance in
C++/Java. Composition nicely solves that problem. In fact, I would argue that
someone who believes code reuse is an appropriate reason to use inheritance
does not understand OO programming as well as they believe.

~~~
palish
This. In fact, a friend of mine swears by writing C++ in a style called
"snippets" --- meaning, whenever it makes sense to do so, he writes new
functionality as a single header and cpp file that has no dependencies
whatsoever on other headers, etc, then open-sources it so that anyone can add
the same functionality to their own C++ projects by just dropping in the code.
A math lib, for example.

~~~
kenjackson
Aren't those also just called "functions"? In this case one function per file?

~~~
palish
No. As soon as your function has a dependency on anything else whatsoever, it
can no longer be copy-and-pasted into another project

A snippet consists of functions which accomplish a specific task. The
important part is that the entire snippet is a single cpp and a single header.
No dependencies.

~~~
masklinn
That's a function with no dependencies. Still a function.

~~~
palish
.... Something is obviously being lost in translation here.

There are certain programming problems which can be solved once and used
forever. The problem wouldn't necessarily be considered a single function.
However, it isn't a massive problem either.

My friend solves these problems by creating a single .cpp and a single .h
file. The .cpp is the implementation; the .h file defines the interface. He
calls this a "snippet".

Now, the power of the snippet is that you can simply copy the .cpp and .h into
_any C++ project anywhere_ and it's good to go. There is no tweaking,
include'ing, anything. It just works.

This code can then serve you for the rest of your life, regardless of what
project you are currently working on. You can say "I've solved that problem
before", and be able to spend literally 30 seconds implementing it into your
current project, because all you have to do is drag'n'drop two files.

~~~
kenjackson
I get the distinction, and its a fair one. Although, I don't get how snippets
could be useful. Especially in C++. It seems like for almost anything
interesting I'm going to want a dependency on the standard library or Boost or
the CRT.

I could imagine some snippets that don't take any dependencies, but they are
pretty few and far between. Do you have pointers to some of the more
interesting snippets he's posted?

~~~
palish
Yeah, check 'em out: <http://www.amillionpixels.us/sourcecode.htm>

There are surprisingly many useful snippets. For example, a single header and
source file for an entire, complete A* pathfinding implementation! That's a
massive timesaver.

~~~
kenjackson
In a lot of the ones titled snippets, I do see dependencies. Some to Windows
DLLs and some to the CRT. But they're relatively self-contained.

Cool stuff. Thanks for the link. Although I'd still call them functions. :-)

------
zby
This is rather well studied subject - but this article does not add anything
to the discussion. It talks a lot about names not much about their meaning.
The only explanation he gives for the advantages or modules over classes is
<blockquote> In Ruby you don't declare your types, so you cannot get ambiguous
instance variables: if you have two instance variables with the same name in
different modules, then they're the same instance variable. </blockquote> as
if this kind of unification of variables would obviously solve anything.

Despite linking to the Wikipedia, he also does provide the right definition of
the diamond problem: <blockquote> This is the dreaded "diamond" problem that
C++ programmers learn to fear: if your class has two superclasses that both
define an instance variable named x, then you can have a hard time specifying
which x you're using. </blocquote> Where is the diamond here?

~~~
RodgerTheGreat
Regarding the diamond problem, I think he means that in the event of multiple
inheritance, your class heirarchy would look like this:

    
    
      Object
       / \
      A   B
       \ /
        C
    

Where A and B are parents of the class C. In most OO languages there will be
an implied parent of A and B, like Object.

------
vog
I was hoping to see a good article about inheritance vs. object composition.

Although Ruby's "modules" are indeed preferable to inheritance they are
usually as inappropriate as inheritance.

To my experience, object composition solves most of the design issues in a
more elegant way. And I wonder why this is still so less understood by most
programmers. It isn't even particularly new. Even the good old GoF patterns
recommend object composition over inheritance, especially in their Smalltalk
examples.

(In their book, they demonstrate each pattern in a static (C++) and a dynamic
(Smalltalk) language, so Ruby programmers should have a deeper look at the
Smalltalk part of the book, rather than imitating the C++ variants of the
patterns.)

~~~
loup-vaillant
I think the reason people prefer inheritance is because it gives them the
illusion that their code is simpler. They don't see the huge interfaces
implied by inheritance because they are implicit.

Composition, on the other hand, is explicit. When you use it, you notice the
complexities. That gives you an incentive to simplify your design, which makes
you write _actually_ simpler code.

~~~
rimantas
The other reason as I see is some quite weird perception that OOP ==
inheritance.

~~~
samg_
OOP is different things to different people. While I agree with you that OOP
!= inheritance, I believe that polymorphism ∈ OOP and inheritance is a part of
polymorphism.

~~~
loup-vaillant
I don't follow you here. Are you saying that inheritance is mandatory to OOP?
(I don't agree nor disagree. I'd just like to know what you mean.)

~~~
samg_
I am not saying that inheritance is mandatory to OOP. I think "mandatory" is
too strong of a word here. As I said, OOP means different things to different
people and I am okay with that.

Speaking for myself, OOP is a way to orchestrate programming on a large scale.
To grow software without growing the frequency, severity, and difficulty of
bugs and without growing costs associated with new features is the desired
result. Component-ized architecture takes great steps to achieve this result.
For this reason, I view OOP as being some combination of: message passing,
encapsulation, and polymorphism. I do not believe this is a complete view of
OOP, nor that there is no viable alternative view of OOP.

------
seshagiric
Old joke in my office:

Q. What is the object oriented way of getting rich?

A. Inheritance

(its a Friday :))

------
substack
Neat. This style of code reuse is a lot like perl6 roles
([http://search.cpan.org/~rkinyon/Perl6-Roles-0.01/lib/Perl6/R...](http://search.cpan.org/~rkinyon/Perl6-Roles-0.01/lib/Perl6/Roles.pm))
or haskell typeclasses: instead of describing how objects fit into a taxonomic
hierarchy, objects or typeclasses are described by what behaviors they
fulfill. For instance, in haskell a Complex type has an instance of Num in
order to define numeric operations like (+) and (-). The emphasis is on what
something _does_ rather than on what it _is_.

~~~
eitland
>instead of describing how objects fit into a taxonomic hierarchy, objects or
typeclasses are described by what behaviors they fulfill.

Can't this be said about Java interfaces too?

~~~
chromatic
Yes and no. Java interfaces are a very degenerate case of roles. They provide
no default behavior (a few constants notwithstanding), they are special cases
in at least part of the type system (declaring a class does not also declare a
role), and I know of no good way to handle conflicts when implementing
multiple interfaces with overlapping requirements.

------
johnzabroski
why is this being upvoted

