Re: Interface inheritance vs Implementation inheritance.
Peter Duniho wrote:
On Tue, 19 Feb 2008 10:08:17 -0800, Daniel Pitts
<newsgroup.spamfilter@virtualinfinity.net> wrote:
[...]
My main point is that classes should use composition to gain behavior,
possibly with an easy mechanism for delegation. The *only* thing that
should be automatically inherited should be the interface. This
eliminates the need for (and usefulness of) the "protected" access
modifier.
I have a sense that in spite of asking the question, you may have
already decided on the answer. I don't intend to get sucked too deep
into this conversation. Especially given the somewhat dubious
cross-posting.
I only cross-posted to cljp because I'm regular there, and appreciate
their input.
That said, I disagree. I do agree that inheriting an implementation and
implementing an interface are not the same thing, but I disagree that
only the latter is a viable approach. Both are important and useful
approaches in OOP. Interfaces are good for when there's a specific
abstract contract that any object ought to be able to fulfill.
Inheriting implementation is good for when an object really "is" a
more-specific version of some existing object. And of course
composition is also useful, when your object isn't really a
more-specific version of some existing object but you still need to take
advantage of an existing implementation of an object.
In Java, why should a new class that inherits Container have to
reimplement all of the Container class's containment interface? If all
you want to do is provide a Container with some specific visual
behavior, why should you also have to reimplement all of the non-visual
containment behavior when there's a working, useful class that already
does all that?
That is a perfectly valid point. My thoughts are that it should be
*easy* to "borrow" implementation from another object, without using
inheritance but instead using composition. To borrow your Container
example: Say you have MyContainer which implements the Container
interface, and delegates (with as clean a syntax as possible) most of
its behavior to another Container instance. You don't have to
re-implement the containment behavior.
Likewise, abstract classes often (in fact, usually IME, otherwise they'd
be interfaces) provide _some_ functionality that only needs one or a few
actual abstract members to be implemented in order to get the full
functionality of the abstract class. For example, InputStream in Java
where you only have to implement "int read()" in a derived class in
order for the other two InputStream methods that read data to work.
There are often performance advantages to overriding those other two
methods as well, but if that's not a design goal why should the
implementor of the derived class be forced to reimplement them anyway
(especially given that they are very likely to just reimplement them
exactly as the abstract class has implemented them, except possibly by
reintroducing all the bugs that the original implementor already found
and fixed in their implementation).
I think what you just described is related to (but not exactly) the
Template design pattern. I think that the problem solved by the Template
pattern can be solved using a callback pattern instead.
Is inheritance overused? I'd agree that it is. Programmers often
inherit when they should either composite or implement an interface
instead. But I disagree that that somehow means that inheriting an
implementation is a priori bad. There is still plenty of good examples
of useful and proper inheritance of an implementation.
I'm not saying that it is always and automatically bad. I guess my main
point was that there are situations where, due to many language
limitations, it is necessary to avoid a massive amounts of boiler-plate
delegation code. If you had a convenient way (say one or two source
lines) to "borrow" all/most implementation from another class, would you
still feel that implementation inheritance is still necessary?
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>