
What OOP Isn't - fogus
http://hacksoflife.blogspot.com/2010/12/what-oop-isnt.html
======
wccrawford
I like how he doesn't even try to defend his stance that inheritance is
completely worthless. I would have said it's a LOT more useful.

~~~
raganwald
Implementation Inheritance is a massive can of worms, and a surprisingly
emotional topic, but I feel fearless today. How do you feel it is useful?

~~~
diN0bot
off the top of my head: dynamic dispatch is a great way to re-use code,
assuming the subclasses really have a "is-a" relationship.

this makes for a double whammy in terms of extensibility, since not only is
the code literally more conducive to later changes, but it meets developer's
expectations, too.

encapsulation and inheritance go hand-in-hand in my book, though i suppose
encapsulation, and the necessary concept of interface contracts, is an axiom
of sorts from which many other good practices can result, especially if there
is also a culture of "communicating for extensibility by new developers
later."

~~~
raganwald
My experience is almost the exact opposite of yours! The first problem is that
the expression "is-a" is notoriously vague. If class A has method a, and class
B subclasses a, can B override method a? In what sense is B an A if it does
not obey Strict Liskov Substitutability?

The second problem is that re-use is an easy problem to solve in any language.
We have delegation, we have proxies, we have so many tools. Why use
inheritance, which mixes two different concepts (is-a and was-a a/k/a is-
implemented-using)?

Lastly, how is the code more conducive to later changes? In my experience, you
now have a problem where changing class A changes the behaviour of every class
that extends A. This is a notoriously tricky problem in the real world. In
theory, that change ought to change every subclass and inheritance is a win.
In practice, the people writing all those subclasses did so making assumptions
about the behaviour of A at the time it was written, much as there are
billions of lines of windows code that depend on its bugs and break the moment
you fix a bug.

Encapsulation is a wonderful thing. I do not see implementation inheritance as
having anything whatsoever to do with encapsulation. If anything, I see the
opposite.

If I write that B is-a A, if these things are fully encapsulated, shouldn't it
be a black box as to how B manages to behave exactly like an A? Maybe there's
some shared code, but then again, shouldn't it be possible for B to use some
other completely different implementation? That's encapsulation to me. Forcing
interface inheritance to be twinned with implementation inheritance _breaks_
encapsulation in my opinion.

~~~
lyudmil
I completely agree with your point. The way inheritance is always taught is
through the "is-a" rule of thumb and I think that's so detrimental to the
students that they'd be better off if they didn't know inheritance existed.
The phrase "X is-a Y" often appears to make sense because of the real world
(e.g. "Cat is-an Animal"), but it makes people forget that it may not make
sense in the world they are trying to model. It may be that the relationship
between a Cat object and an Animal object is completely different in your
system than in the real world. If it is, then you run into the problems with
future changes you already mentioned.

I also second your point on code reuse. Code reuse/removal of duplication is
the main reason behind all programming languages and paradigms. Inheritance is
a tool provided by OOP languages. Therefore, to say that it enables code reuse
is basically trivial.

~~~
raganwald
I have discovered a truly marvellous follow-up to your comment, which this box
is too small to contain.

[http://github.com/raganwald/homoiconic/blob/master/2010/12/o...](http://github.com/raganwald/homoiconic/blob/master/2010/12/oop.md#readme)

~~~
lyudmil
Yes, absolutely. Thinking about design in terms of defining an ontology is a
great insight. Every object has a name and is therefore a part of some sort of
semantics. However, what it does (it's meaning) is up to the designer.
Therefore, words are naturally overloaded - they represent what we they do in
reality, and their analog in our system.

As an example, let's assume we're developing a game where cats battle all
sorts of other animals for survival. Certainly, the designer has good reason
to call the object representing the protagonists in the game Cat. The
programmer also has good reasons to call the enemies of the cat Animals, since
they will all do the same thing (e.g. attack the cat). However, in this case a
Cat is definitely not an Animal. Cat is an overloaded word - it no longer
means "feline". Similarly, Animal means something completely different - it's
more akin to "enemy". If we could substitute the "natural" ontology of these
words with the one our objects define, we would be able to tell that the
statement "A Cat is an Animal" is senseless.

I think OOP actually tries to take advantage of the "natural" ontologies we
have constructed through experience. This is why this is such a subtle design
issue. I'm not quite ready to say it "gets it backwards", but it certainly
doesn't mirror the way we naturally look at the world.

I hope I'm mirroring and expanding on what's been said here. I'd love to read
your thoughts.

