There were quite a few interesting comments on my previous entry, both on my
weblog and on
TheServerSide thread. I
will address them in turn and I’ll take this opportunity to clarify my position
on inheritance.
Howard writes:
I tend to make as many of my methods private as possible. I occasionally even
use final on non-private methods (but rarely).
This is a very good practice. Interestingly, it’s a lesson that we
learned from C++, where the community actually took it one step further. Back
then, I remember reading an article by a C++ guru actually recommending to
maximize the number of static methods in your code. This article
caused quite a stir as you can guess since a lot of developers equate static
methods to global variables. Nevertheless, the author mentioned that
static methods are the most decoupled methods you can have in your code.
Something to think about.
Vincent says:
I personnally try not to extend specialized TestCase. I prefer to work with
Suites. I think this is the "official" way to extend JUnit
I don’t know how official it is, but point taken, Vincent. I think I’ll
head this way as well, maybe it will decrease the amount of frustration I have
with JUnit 🙂
Hristo is more radical:
Yes inheritance IS EVIL and should almost always be replaced with
compositions (or AOP introductions).
I disagree with this, which is too radical in my taste. Neither
inheritance nor delegation/composition/introduction are silver bullets. I
am not going to run an exhaustive list of their pros and cons, but I think one
of the salient points that should make you choose one over the other is that of
Typing. When you extend, your subclass can be substituted for its parent
class (also referred to as the
Liskov
Substitution Principle). There are quite a few cases when such a
property is not only convenient: it is the only sound design choice.
On the other hand, delegation is more flexible and more dynamic. This is
also something that can be a requirement.
Hristo also uses
this interview
of James Gosling to bash inheritance, whereas Gosling seems actually to be
quite fond of inheritance:
I personally tend to use inheritance more often than anything else.
Then Hani sets the debate back on track with his usual lucid observation:
Inheritance isn’t evil, people who don’t understand it or design for it are.
Which is pretty much what I said in the paragraph above, although in
different terms since I couldn’t dream of ever reaching Hani’s mastery of
concision and punch-packing.
Bo notices:
Um, as far as I can tell, you haven’t made a case against not calling super
you’ve made a case about why you should put initialization logic in
constructors. (Hint: base class constructors always get called).
Right, constructors are always called and the invocation of super in their
code is enforced by the compiler, which is why I made them an exception in my
original article ("whenever you feel the need to call super inside a method
that is not a constructor, it’s a code smell"). And I agree that
initialization logic should be in constructors, but it’s not always
achievable. Sometimes, extra initialization has to happen after the object
is created.
It’s too bad that java doesn’t have an overrides keyword yet (1.5 will
introduce @Overrides)
This keyword won’t change anything to the problem at hand, except that the
compiler might be able to notice a typo. But there will certainly be no
implicit call to super.
IMO calling super should be the first thing you do when you override a method
In my experience, close to none of the code I work with or read ever does
that. Most of the methods that override a parent method simply replace the
logic of the overridden method. You might call that misuse of inheritance,
and I won’t necessarily disagree with you, but this is a different topic.