Interface inheritance vs Implementation inheritance.

D

Daniel Pitts

(x-posted to c.object and c.l.java.programmer)
First, a quick bit about my background; most of my OO experience comes
from Java, with some C++ in my past. Recently in comp.object, there was
a thread "Inheritance of implementation: what is reason of". While the
subject line could use some grammatic tweaking, the point was eventually
made clear.

I was thinking about it, and it seems to me that implementation
inheritance is a convenience that leads to bad design and mistakes. By
convenience, I mean that often a programmer will design the an interface
and the implementation together in one source unit (e.g. a class).
Alternatively, you can define a separate interface (lets call it IFoo)
in one source unit, and an implementation (FooImpl). FooImpl is *also*
an interface in many languages, it just happens to have the associated
implementation.

So far, not that big of a deal. The convolution comes when you add in
access modifiers. For instance, in Java you can mark methods/fields as
private, protected, package-private, or public. Now, you have up to 4
interfaces to the implementation. Only certain code units can see some
of the interfaces, but managing that contract becomes troublesome,
especially for the "protected" interface, as many programmers don't
design their classes for inheritance but the class gets used that way.

To me, polymorphic behavior is important, and "implementation sharing"
is a very useful convenience. I think that they are often co-mingled
concepts that should be separated. I have a few ideas on how I might do
this, at the language level, but I wanted to see if my above thoughts on
the subject stirred any interesting discussions.

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

andrew queisser

Daniel Pitts said:
(x-posted to c.object and c.l.java.programmer)

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.

In C++ there are various ways implementation inheritance is useful in ways
other than inheritance of default implementation, e.g. STL, ATL, WTL, all of
which use some form of implementation inheritance to achieve efficiency.

I think the primary problem people are concerned about is implementation of
inheritance for virtual functions. Perhaps this distinction is not
meaningful outside of the C++ world.

Andrew
 
P

Peter Duniho

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

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?

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

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.

Pete
 
D

Daniel Pitts

Peter said:
[...]
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?
 
P

Peter Duniho

[...]
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?

I guess I can only at this point answer "it depends". It seems to me that
the current, widely-used implementation inheritance syntax is pretty much
just that: a convenient way to borrow implementation from another class.

I would have to see what this alternative syntax would look like to answer
more definitively, but it's not clear to me that it'd be any different in
practice from simply inheriting an implementation directly (assuming that,
as with interfaces, a "borrowing" class still tests "true" for whether it
"is" one of these "borrowed" things...if that's not the case, then I'd say
that's a glaring omission of the proposal).

Or, looking at the question from another angle, if it's okay to "borrow"
implementation from another class, what does it matter whether it was
borrowed in the form of inheritance or in the form of a new type of
composition that looks just like inheritance?

I'm reading this in the Java newsgroup, and perhaps the "comp.object"
crowd has a more thorough academic understanding of OOP practices and
principles than I do. But I admit, based on what you've written so far
I'm not really clear on the distinction between the way things are now and
what you're suggesting they could be, at least from a practical standpoint.

Pete
 
P

Patricia Shanahan

Peter Duniho wrote:
....
Or, looking at the question from another angle, if it's okay to "borrow"
implementation from another class, what does it matter whether it was
borrowed in the form of inheritance or in the form of a new type of
composition that looks just like inheritance?
....

I think the big question is what gets exposed to users of the borrowing
class.

To make this a bit more specific, consider ArrayList. It implements a
series of interfaces. Those describe the general behavior its callers
can depend on: it's a list, it has fast random access, it can be cloned
and serialized, and it has an Iterator.

In addition, it extends AbstractList. That seems to me to be part of its
implementation, and not something I would use in my code. And yet, a
class outside java.util could declare:

AbstractList<String> someList = new ArrayList<String>();

It might be advantageous to split AbstractList, for example to provide
different implementations depending on whether the list has fast random
access. That cannot be done, because of the public nature of the uses of
AbstractList.

Patricia
 
D

Daniel Pitts

Peter said:
[...]
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?

I guess I can only at this point answer "it depends". It seems to me
that the current, widely-used implementation inheritance syntax is
pretty much just that: a convenient way to borrow implementation from
another class.
Currently, inheritance of classes "borrows" both the implementation
*and* interface. The thing is that interface and implementation are
borrowed together, and you have to take extra steps if you only want the
implementation or only the interface. I think it might be good to
separate those concepts.
I would have to see what this alternative syntax would look like to
answer more definitively, but it's not clear to me that it'd be any
different in practice from simply inheriting an implementation directly
(assuming that, as with interfaces, a "borrowing" class still tests
"true" for whether it "is" one of these "borrowed" things...if that's
not the case, then I'd say that's a glaring omission of the proposal).
If the interface "lives" separately from the implementation, then the
borrow can choose to also borrow the interface (or some parent
interface, or some composite interface).
Or, looking at the question from another angle, if it's okay to "borrow"
implementation from another class, what does it matter whether it was
borrowed in the form of inheritance or in the form of a new type of
composition that looks just like inheritance?
Because the borrowing can be more pick-and-choose in the new way,
instead of the all-or-nothing of inheritance. Also, there are times when
your interface maps one-to-one to another class for a few methods. It
could be easier to pick out those methods.
I'm reading this in the Java newsgroup, and perhaps the "comp.object"
crowd has a more thorough academic understanding of OOP practices and
principles than I do. But I admit, based on what you've written so far
I'm not really clear on the distinction between the way things are now
and what you're suggesting they could be, at least from a practical
standpoint.
I guess the main difference is the syntax, but I believe it adds
flexibility too.
 
D

Daniele Futtorovic

Peter said:
[...] 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?

I guess I can only at this point answer "it depends". It seems to
me that the current, widely-used implementation inheritance syntax
is pretty much just that: a convenient way to borrow implementation
from another class.
Currently, inheritance of classes "borrows" both the implementation
*and* interface. The thing is that interface and implementation are
borrowed together, and you have to take extra steps if you only want
the implementation or only the interface. I think it might be good
to separate those concepts.
I would have to see what this alternative syntax would look like to
answer more definitively, but it's not clear to me that it'd be
any different in practice from simply inheriting an implementation
directly (assuming that, as with interfaces, a "borrowing" class
still tests "true" for whether it "is" one of these "borrowed"
things...if that's not the case, then I'd say that's a glaring
omission of the proposal).
If the interface "lives" separately from the implementation, then the
borrow can choose to also borrow the interface (or some parent
interface, or some composite interface).
Or, looking at the question from another angle, if it's okay to
"borrow" implementation from another class, what does it matter
whether it was borrowed in the form of inheritance or in the form
of a new type of composition that looks just like inheritance?
Because the borrowing can be more pick-and-choose in the new way,
instead of the all-or-nothing of inheritance. Also, there are times
when your interface maps one-to-one to another class for a few
methods. It could be easier to pick out those methods.
I'm reading this in the Java newsgroup, and perhaps the
"comp.object" crowd has a more thorough academic understanding of
OOP practices and principles than I do. But I admit, based on what
you've written so far I'm not really clear on the distinction
between the way things are now and what you're suggesting they
could be, at least from a practical standpoint.
I guess the main difference is the syntax, but I believe it adds
flexibility too.

/* The following deliberately sets itself strictly within the context of
the Java Programming Language, as it often most beneficial to have a
practical reference to focus the discussion. */

It seems to me all practical examples you gave in this thread are
feasible with the current grammar of Java. There are two discrete
models, one for "borrowing" an interface and one for "borrowing" an
implementation; the first one is called implementing an interface and
the second one extending a class.
The practice of always providing both for all classes isn't ubiquitous,
or even widespread. But, while I grant this may cause you much grief on
diverse occasions, it is simply not an argument against the grammar of
Java, but only potentially against some of its uses.
On the subject of "borrowing an implementation", let me point out that
getting rid of protected modifiers, which you seem to aim at, would
effectively _force_ upon you _all_ the implementation that isn't public
-- so much for "borrowing can be more pick-and-choose".

The use of composition in a given class is clearly a good idea and
obviously superior to inheritance simply in that you can only inherit
once, but can compose many times. There are various stances one can take
towards composing, from aggressive encapsulating of any functionality
that lurks its head to lazily refactoring en masse. Note, however, that
composition does not replace, or indeed affect, inheritance essentially:
it merely replaces it in the context of one given class. Talking of
composition merely _shifts_ the question of inheritance towards the
classes actually implementing the encapsulated functionality. Now you
may argue that, since through composition you grant the API user means
to replace functionality in transparent manner, you can keep all your
implementations of the encapsulated functionality locked tight. This
would surely be a valid choice, and it may for any given case be
justified or not -- but one thing's for sure and that's that you would
be giving your customers less for their money by prohibiting re-use of
code (unless you make it public throughout, which I don't suppose you'd
advocate).

You've been occasionally talking about "clean syntax", "few lines of
code", suggesting your aim was at least partially at some kind of
syntactic sugar. So let me state this: Java boilerplate code is GREAT.
And in my view *any* request for modification of the JLS, the sole
argument in favour of which is that it saves typing, does not deserve
attention (nota bene: shorter syntax is not the same thing as greater
clarity).
What in my opinion is one of the greatest things about Java is that, at
the basic level, the language features very few denizens: objects,
primitives, classes, interfaces, functions, fields -- that's about it.
With these basic entities, such high-level concepts as callbacks,
closures or concurrent APIs can be built. Entirely transparently so. If
someone wishes to see how it's done, they can, by simply reading the
source code (except for native methods). They can reproduce it freely.
No behind-the-scenes voodoo. Yes, that's it in two words: no voodoo.

At least that's what it was like until they introduced the enhanced
for-loop back in Tiger (I'm not entirely sure it was the first
occurrence, but it's just an example, don't quote me on that). And I can
only hope they won't get through with the closures stuff they're
planning for 1.7. This to me is clearly a step in the wrong direction,
because it /hides/ what's going on. It's voodoo. The enhanced for-loop
takes an Iterable, initialises an iterator, and repeatedly calls next()
while checking hasNext(). We know that because it's written in the
specification. But the point is that nowhere can we see that in plain
Java code anymore.
Now don't get me wrong: the enhanced for-loop is really quite a pleasure
to use, and even I, who am reluctant to it, have found myself making
increasing use of it. But when it comes down to it and I am confronted
with the choice between a short syntax where it's unclear what's going
on and a longer syntax where you see precisely what's going on -- I'm
always going to side with the latter. When you know what you're doing
you can always assess that each bit of effort you provide, no matter how
much of it is overall necessary, is productive; while in the opposite
case you cannot tell whether it may be unproductive or, even worse,
counter-productive.

df.
 
D

Daniel Pitts

Daniele said:
Peter said:
On Tue, 19 Feb 2008 13:27:19 -0800, Daniel Pitts

[...] 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?

I guess I can only at this point answer "it depends". It seems to
me that the current, widely-used implementation inheritance syntax
is pretty much just that: a convenient way to borrow implementation
from another class.
Currently, inheritance of classes "borrows" both the implementation
*and* interface. The thing is that interface and implementation are
borrowed together, and you have to take extra steps if you only want
the implementation or only the interface. I think it might be good
to separate those concepts.
I would have to see what this alternative syntax would look like to
answer more definitively, but it's not clear to me that it'd be
any different in practice from simply inheriting an implementation
directly (assuming that, as with interfaces, a "borrowing" class
still tests "true" for whether it "is" one of these "borrowed"
things...if that's not the case, then I'd say that's a glaring
omission of the proposal).
If the interface "lives" separately from the implementation, then the
borrow can choose to also borrow the interface (or some parent
interface, or some composite interface).
Or, looking at the question from another angle, if it's okay to
"borrow" implementation from another class, what does it matter
whether it was borrowed in the form of inheritance or in the form
of a new type of composition that looks just like inheritance?
Because the borrowing can be more pick-and-choose in the new way,
instead of the all-or-nothing of inheritance. Also, there are times
when your interface maps one-to-one to another class for a few
methods. It could be easier to pick out those methods.
I'm reading this in the Java newsgroup, and perhaps the
"comp.object" crowd has a more thorough academic understanding of
OOP practices and principles than I do. But I admit, based on what
you've written so far I'm not really clear on the distinction
between the way things are now and what you're suggesting they
could be, at least from a practical standpoint.
I guess the main difference is the syntax, but I believe it adds
flexibility too.

/* The following deliberately sets itself strictly within the context of
the Java Programming Language, as it often most beneficial to have a
practical reference to focus the discussion. */

It seems to me all practical examples you gave in this thread are
feasible with the current grammar of Java. There are two discrete
models, one for "borrowing" an interface and one for "borrowing" an
implementation; the first one is called implementing an interface and
the second one extending a class.
The practice of always providing both for all classes isn't ubiquitous,
or even widespread. But, while I grant this may cause you much grief on
diverse occasions, it is simply not an argument against the grammar of
Java, but only potentially against some of its uses.
On the subject of "borrowing an implementation", let me point out that
getting rid of protected modifiers, which you seem to aim at, would
effectively _force_ upon you _all_ the implementation that isn't public
-- so much for "borrowing can be more pick-and-choose".
Anything that was "protected" is still a "public interface" to the
inheritors. You can separate that out quite easily in all the
circumstances I can think of.
The use of composition in a given class is clearly a good idea and
obviously superior to inheritance simply in that you can only inherit
once, but can compose many times. There are various stances one can take
towards composing, from aggressive encapsulating of any functionality
that lurks its head to lazily refactoring en masse. Note, however, that
composition does not replace, or indeed affect, inheritance essentially:
it merely replaces it in the context of one given class. Talking of
composition merely _shifts_ the question of inheritance towards the
classes actually implementing the encapsulated functionality. Now you
may argue that, since through composition you grant the API user means
to replace functionality in transparent manner, you can keep all your
implementations of the encapsulated functionality locked tight. This
would surely be a valid choice, and it may for any given case be
justified or not -- but one thing's for sure and that's that you would
be giving your customers less for their money by prohibiting re-use of
code (unless you make it public throughout, which I don't suppose you'd
advocate).
Since the "protected interface" is specific to an implementation, it
should be called out differently IMO. As far as re-use goes, its
important to limit re-use to things you expect to maintain in the
future. You can still add the hooks to have extensibility in your code,
enabling re-use. You just use a different pattern.
You've been occasionally talking about "clean syntax", "few lines of
code", suggesting your aim was at least partially at some kind of
syntactic sugar. So let me state this: Java boilerplate code is GREAT.
And in my view *any* request for modification of the JLS, the sole
argument in favour of which is that it saves typing, does not deserve
attention (nota bene: shorter syntax is not the same thing as greater
clarity).
I agree short/clever != clear, and this is not in the context of Java,
despite the fact that I posted to cljp :)
The syntax would be explicit and compact. Having not thought greatly
into it. "MyFoo extends Foo {}" might become "MyFoo implements Foo { Foo
foo; delegate "*" to foo; }

Yes, its a little more typing, but you can replace that "*" with more
specific names, etc... Thats where you get the pick-and-choose. It
also allows inversion-of-control in the inheritance structure. Think "I
want a MyFoo that extends FooBar, and I want another MyFoo that extends
FooLish".
What in my opinion is one of the greatest things about Java is that, at
the basic level, the language features very few denizens: objects,
primitives, classes, interfaces, functions, fields -- that's about it.
With these basic entities, such high-level concepts as callbacks,
closures or concurrent APIs can be built. Entirely transparently so. If
someone wishes to see how it's done, they can, by simply reading the
source code (except for native methods). They can reproduce it freely.
No behind-the-scenes voodoo. Yes, that's it in two words: no voodoo.
I agree with that. I'm not suggesting modifying Java, it would have to
be another (possibly not-yet-existent) language.
At least that's what it was like until they introduced the enhanced
for-loop back in Tiger (I'm not entirely sure it was the first
occurrence, but it's just an example, don't quote me on that). And I can
only hope they won't get through with the closures stuff they're
planning for 1.7. This to me is clearly a step in the wrong direction,
because it /hides/ what's going on. It's voodoo. The enhanced for-loop
takes an Iterable, initialises an iterator, and repeatedly calls next()
while checking hasNext(). We know that because it's written in the
specification. But the point is that nowhere can we see that in plain
Java code anymore.
Now don't get me wrong: the enhanced for-loop is really quite a pleasure
to use, and even I, who am reluctant to it, have found myself making
increasing use of it. But when it comes down to it and I am confronted
with the choice between a short syntax where it's unclear what's going
on and a longer syntax where you see precisely what's going on -- I'm
always going to side with the latter. When you know what you're doing
you can always assess that each bit of effort you provide, no matter how
much of it is overall necessary, is productive; while in the opposite
case you cannot tell whether it may be unproductive or, even worse,
counter-productive.
True, and hopefully the "example" syntax I use above helps to show that
I'm actually exposing more information rather than less. The "delegate"
keyword would expose exactly which methods (by name or whatever) are
being exposed.

Thanks (everyone) for the feedback so far. Even if it appear(s/ed) that
I already made up my mind, it is something that I'm working out for
myself, but want feedback to help confirm or deny my suspicions.
 
P

Patricia Shanahan

Daniele Futtorovic wrote:
....
With these basic entities, such high-level concepts as callbacks,
closures or concurrent APIs can be built. Entirely transparently so. If
someone wishes to see how it's done, they can, by simply reading the
source code (except for native methods). They can reproduce it freely.
No behind-the-scenes voodoo. Yes, that's it in two words: no voodoo.

I've heard the "no voodoo" argument many times before, initially from
people telling me why assembly languages were better than Fortran or
Algol. Later, procedural languages were better than OO, because you can
see exactly what function will be invoked, no virtual call voodoo.

The increasing semantic gap between what the programmer writes and
what the processor does has been a major theme of programming language
development. The effect has been to greatly increase the effectiveness
of programmers by automating a lot of details.

What's different this time? Does Java really have *exactly* the right
amount of voodoo, so that adding any more will take it past the current
sweet spot?
At least that's what it was like until they introduced the enhanced
for-loop back in Tiger (I'm not entirely sure it was the first
occurrence, but it's just an example, don't quote me on that).

I like the enhanced for-loop. If I just want to do something to every
element in a collection an enhanced for-loop expresses my intent more
directly and clearly than an Iterator idiom.

Patricia
 
L

Lasse Reichstein Nielsen

Patricia Shanahan said:
To make this a bit more specific, consider ArrayList. It implements a
series of interfaces. Those describe the general behavior its callers
can depend on: it's a list, it has fast random access, it can be cloned
and serialized, and it has an Iterator.

In addition, it extends AbstractList. That seems to me to be part of its
implementation, and not something I would use in my code. And yet, a
class outside java.util could declare:

AbstractList<String> someList = new ArrayList<String>();

It might be advantageous to split AbstractList, for example to provide
different implementations depending on whether the list has fast random
access. That cannot be done, because of the public nature of the uses of
AbstractList.

Agreed.
I wouldn't mind a language where implementation inheritance wasn't public,
i.e., your type only consists of interfaces. If you extend another class,
you also implements its interfaces, but the extended class is not part
of your type.

And I would also like an easy way to create a composition, e.g.,

class Foo implements Bar(b) {
private Bar barbarbar implements Bar; // or delegates Bar
public Foo(int i) {
super(i);
this.barbarbar = new Bar(i);
}
//...
}

/L
 
R

Robert Martin

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.

Polymorphism is a good thing, and the use of interfaces to achieve
polymorphism should be encouraged in Java. On the other hand, there
are times when inheritance of implementation is -- pleasant.

The standard Observer is a common enough example. Observable classes
need to be able to register and notify observers. We can create a
non-polymorphic class that provides this behavior:

public class Subject {
private List<Observer> observers = ArrayList<Observer>();
public void register(Observer o) {observers.add(o);}
public void notify() {
for (Observer o : observers)
o.update();
}
}

Now any observable can inherit this class and enjoy the implementation
of register and notify. Note that there is no polymorphism involved,
or intended. We simply want the implementation.

Of course the creators of Java were too wimpy to add true multiple
inheritance. So by inheriting Subject, we use up the one and only
inheritance slot for our observable class. That's a shame. If Java
had true multiple inheritance then we'd be able to mix-in simple
implementations like this, with other classes.

As things stand, it is probably best to use composition to bring
Subject into the observable, and use delegation to call the register
and notify functions. But not because polymorphic interfaces are always
better; rather because Java was crippled by the decision to turn
multiple inheritance into the bogey man.
 
R

Robert Martin

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.

True, but you DO have to write all the delegating functions. Ick. Why
should I have to write a bunch of brain-dead delegation functions every
time I want to reuse some nice piece of implementation.

It would be trivial to add language feature that did
composition-and-delegation for you. It might look like this:

class MyContainer composes SomeContainer {
...
}

This would create a hidden instance variable for SomeContainer, and
automatically write delegation functions in MyContainer.

Indeed, you might be able to compose more than one class. Let's say
you wanted to have a contaier that was observable:

class MyContainer composes SomeContainer, Subject {
...
}

How cool would this be! Automatic reuse through composition!!!

There is a name for this feature.

It's called Multiple Inheritance.
 
R

Robert Martin

I think the big question is what gets exposed to users of the borrowing
class.

To make this a bit more specific, consider ArrayList. It implements a
series of interfaces. Those describe the general behavior its callers
can depend on: it's a list, it has fast random access, it can be cloned
and serialized, and it has an Iterator.

In addition, it extends AbstractList. That seems to me to be part of its
implementation, and not something I would use in my code. And yet, a
class outside java.util could declare:

AbstractList<String> someList = new ArrayList<String>();

It might be advantageous to split AbstractList, for example to provide
different implementations depending on whether the list has fast random
access. That cannot be done, because of the public nature of the uses of
AbstractList.

This is the reason that C++ has private inheritance. A privately
inherited base class is inaccessible to any users or further subclasses.
 
R

Robert Martin

I wouldn't mind a language where implementation inheritance wasn't public,
i.e., your type only consists of interfaces. If you extend another class,
you also implements its interfaces, but the extended class is not part
of your type.

You mean like in C++?

class MyContainer : private SomeContainer {
....
}
And I would also like an easy way to create a composition, e.g.,

class Foo implements Bar(b) {
private Bar barbarbar implements Bar; // or delegates Bar
public Foo(int i) {
super(i);
this.barbarbar = new Bar(i);
}
//...
}

If you think about that a bit longer, you'll realize that an easy way
to create composition IS inheritance. Or rather, inheritance is an
easy way to create composition.

Every method of the component gets redeclared in the composer. When
those methods are called on the composer, the component's
implementation is invoked.

Now change the words composer to base, and component to derivative and
you'll see the sentence is true.

Perhaps what you are after is a way to make sure that the composer
cannot be cast (explicitly or implicitly) to the component. That's
what private inheritance gives you.

I conclude from this that we'd all be happy if Java had multiple
inheritance and private inheritance.

;-)
 
S

Silvio Bierman

Robert said:
If you think about that a bit longer, you'll realize that an easy way to
create composition IS inheritance. Or rather, inheritance is an easy
way to create composition.

Every method of the component gets redeclared in the composer. When
those methods are called on the composer, the component's implementation
is invoked.

Now change the words composer to base, and component to derivative and
you'll see the sentence is true.

Perhaps what you are after is a way to make sure that the composer
cannot be cast (explicitly or implicitly) to the component. That's what
private inheritance gives you.

I conclude from this that we'd all be happy if Java had multiple
inheritance and private inheritance.

;-)

I disagree. Inheritance and interfaces a la Java have one important
distinction: interfaces introduce no implicit implementation of methods.
Since Java does not support multiple inheritance implementation
inheritance is too limited for many use cases. C++ supports MI but in a
very disturbed way (although I was quite happy with it when it was
introduced into the language I have learned to really hate it). The
issues of virtual bases and multiple down-cast paths leading to
different implementations of the same function signature are painful. It
is unclear how any implementation of multiple implementation inheritance
could circumvent these issues.

The advantage of the Java interface concept is that a class implementing
an interface (and not extending any other class than Object) will have
to explicitly define how the interface methods are implemented. If it
extends multiple interfaces with shared function signatures the seaming
ambiguity is resolved at the class level itself.

Unfortunately Java lacks a simple way of expressing interface
delegation. I would have loved something like:

interface I1
{
public void f1();
public void f2();
public void f3();
}

class C1 implements I1
{
public void f1() { /*...*/ }
public void f2() { /*...*/ }
public void f3() { /*...*/ }
}

class C2 implements I1, I2
{
private C1 c1a;
private C1 c1b;
public I1() { return c1a != null ? c1a : c1b; } /* NOT SUPPORTED */
public void f2() { /* THIS IS AN OVERRULE IMPLEMENTATION */ }
}

where the constructor-like syntax of the 'public I1() { /*...*/}'
notation implies that all methods declared in I1 and not declared in C2
or I2 are implicitly implemented such that given a C2 reference c2
calling c2.f1() is equal to c2.I1().f2().


This syntax would be ideal for implementing partial delegations of
interfaces with many methods when writing wrapper classes (the JDBC or
Servlet interfaces anyone?).

Would such syntax/semantics exist I would be happy to drop
implementation inheritance in most places.

Kind regards,

Silvio Bierman
 
D

Daniele Futtorovic

Daniele Futtorovic wrote: ....

I've heard the "no voodoo" argument many times before, initially from
people telling me why assembly languages were better than Fortran or
Algol. Later, procedural languages were better than OO, because you
can see exactly what function will be invoked, no virtual call
voodoo.

The increasing semantic gap between what the programmer writes and
what the processor does has been a major theme of programming
language development. The effect has been to greatly increase the
effectiveness of programmers by automating a lot of details.

What's different this time? Does Java really have *exactly* the right
amount of voodoo, so that adding any more will take it past the
current sweet spot?

You're right, so maybe the emphasis shouldn't be on /how much/ voodoo,
but on /how/ voodoo. The point would be to find a minimal set of
building blocks, of basic entities, which encapsulate the voodoo, and to
keep the set minimal. Especially not to inflate it with synonyms which
make no semantical addition.
I like the enhanced for-loop. If I just want to do something to every
element in a collection an enhanced for-loop expresses my intent
more directly and clearly than an Iterator idiom.

Not functionally so, for functionally, you are using an Iterator. What's
happened is that, from the point of view of the code, you've introduced
a new entity which, though linguistically distinct, makes no semantic
addition. It's a synonym.

df.
 
H

H. S. Lahman

Responding to Pitts...
I was thinking about it, and it seems to me that implementation
inheritance is a convenience that leads to bad design and mistakes. By
convenience, I mean that often a programmer will design the an interface
and the implementation together in one source unit (e.g. a class).
Alternatively, you can define a separate interface (lets call it IFoo)
in one source unit, and an implementation (FooImpl). FooImpl is *also*
an interface in many languages, it just happens to have the associated
implementation.

I think it is important to distinguish between simple implementation
inheritance and overrides of implementation inheritance. Overrides have
proven to be a Really Bad Idea if one cares about maintainability.

However, simple implementation inheritance is almost always benign. To
create a situation where maintenance of the generalization can break
existing clients requires a large and complicated generalization, which
should make one look for delegation solutions in the first place. Also,
the foot-shooting examples I've seen with simple implementation
inheritance can be attacked on other design grounds.

The problem is that every OOPL I know that supports implementation
inheritance also supports overrides because the underlying jump table
mechanism is the same. But just because a language supports a feature
doesn't mean one needs to use it. I think an OOA/D methodological
prohibition of using overrides is sufficient.
So far, not that big of a deal. The convolution comes when you add in
access modifiers. For instance, in Java you can mark methods/fields as
private, protected, package-private, or public. Now, you have up to 4
interfaces to the implementation. Only certain code units can see some
of the interfaces, but managing that contract becomes troublesome,
especially for the "protected" interface, as many programmers don't
design their classes for inheritance but the class gets used that way.

IMO, the public/private stuff found in OOPLs is just syntactic sugar
that saves the developer some keystrokes at the cost of potentially
introducing foot-shooting. There is nothing these qualifiers provide
that one could not do with different developer-defined interfaces and
associating specific clients with specific interfaces. [In the
translation MDA profile I use for OOA, those qualifiers are not
available. A full code generator has no problem generating correct code
without them.]

[FWIW, I think Protected is a kludge and the only place I would use it
is to support a unit test harness -- for which it is very convenient.
But let's not go there...]
To me, polymorphic behavior is important, and "implementation sharing"
is a very useful convenience. I think that they are often co-mingled
concepts that should be separated. I have a few ideas on how I might do
this, at the language level, but I wanted to see if my above thoughts on
the subject stirred any interesting discussions.

I agree they are different things. But I think one can prevent them from
becoming co-mingled in a detrimental way methodologically. The OOPLs
/implement/ OOA/D; methodologies drive OOA/D.

[Note that the OOPLs do much more egregious things, such as combining
message and method, simply because they are 3GLs. But those things are
rendered harmless by getting the OOA/D right.]
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.

Unrestrained composition has its own set of problems as it can trash
object cohesion.


--
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
(e-mail address removed)
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
(e-mail address removed) for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH
 
P

Patricia Shanahan

Daniele said:
On 2008-02-20 02:47 +0100, Patricia Shanahan allegedly wrote: ....


You're right, so maybe the emphasis shouldn't be on /how much/ voodoo,
but on /how/ voodoo. The point would be to find a minimal set of
building blocks, of basic entities, which encapsulate the voodoo, and to
keep the set minimal. Especially not to inflate it with synonyms which
make no semantical addition.

All you really need is a Turing machine. Its basic entities are a state
machine, a current state, and a tape with a single read/write head. Or,
to be a bit more practical, consider the original MIPS instruction set.
Its assembly language is very simple, with few basic entities.

However, I find it far easier to express my programs in Java than in any
assembly language.
Not functionally so, for functionally, you are using an Iterator. What's
happened is that, from the point of view of the code, you've introduced
a new entity which, though linguistically distinct, makes no semantic
addition. It's a synonym.

Sure. Even assembly languages add new entities which, though
linguistically distinct, make no semantic addition. For example, "nop"
is often provided as a mnemonic, but mapped to some existing operation
that does nothing. What's wrong with that, as long as it makes the
resulting programs a clearer expression of the programmer's intent?

Patricia
 
M

Mike Schilling

Robert said:
True, but you DO have to write all the delegating functions. Ick.
Why should I have to write a bunch of brain-dead delegation
functions
every time I want to reuse some nice piece of implementation.

It would be trivial to add language feature that did
composition-and-delegation for you. It might look like this:

class MyContainer composes SomeContainer {
...
}

This would create a hidden instance variable for SomeContainer, and
automatically write delegation functions in MyContainer.

It would also be trivial for an IDE to generate the delegation methods
for you, and no languages changes are required for that.
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top