The Artima Developer Community
Sponsored Link

Re: C++ templates don't provide polymorphism

Advertisement

Advertisement

This page contains an archived post to the Design Forum (formerly called the Flexible Java Forum) made prior to February 25, 2002. If you wish to participate in discussions, please visit the new Artima Forums.

Message:

Re: C++ templates don't provide polymorphism

Posted by Lois Goldthwaite on 17 Dec 1998, 5:15 AM

> Dear Lois,

> I liked a lot your way of using C++ Templates.
> But I think there is a little problem with your example :
> it does not REALLY provide polymorphism -

Actually, I don't think polymorphism is exactly the right word for this
situation, but since Bill originally started with the premise
that interfaces provide "more polymorphism" we've kept it in the
discussion. What is the right word? Maybe "roles" or something
like "temporarily aggregated functionality"? (TAF for short -- a
new three-letter acronym! :-)

Some design methodologies and languages
make a distinction between "type" -- the public interface of
something -- and "class" -- the kind of object that implements
the behavior promised by that interface. A human piano player and
a CD Walkman would both respond to "play it again, Sam" with similar
outputs but by very different methods.

> - you can't write :
>


> // example 1
> Talkative t;
> t = makeTalkative(aDog); t.talk();
> //...
> t = makeTalkative(aCuckooClock); t.talk();
>

> The first line is incorrect - or am I wrong ?
> But your idea still works if you write :

>


> // example 2.1
> class abstract BaseTalkative {
> abstract void talk();
> };
> template < class T >
> class Talkative : public BaseTalkative { // I've moved your ':'
> T& t;
> public:
> void talk() { /*...*/ }
> };
>

> And then the previous example works,
> if you replace the first line with:

>


> // example 2.2
> BaseTalkative t;
>

You're absolutely correct about all of this. And doesn't it bring
a purer, more interface-like feel to the code?

> > The C++ template approach has the advantage that run-time
> > polymorphism can be attached to a class object without requiring
> > any change to that class's code.

> Huho ! This is definitely not RUNTIME polymorphism.
> Templates work because you know at COMPILATION time that all the
> classes you use for T do have a talk method (and for those which
> don't, you provide it by naming the classes, still at compilation
> time).

Oops, sorry, I slipped up there; thanks for catching it.

Templates do provide so-called
compile-time polymorphism, as opposed to the run-time polymorphism
of inheritance and virtual functions. Checking validity at compile
time is considered a feature in C++. In Java it's so easy to lose
the static type of an instance (because Hashtables only hold
references to generic Objects, and so forth) that you're always
having to use casts, and check for BadCastExceptions, and handle
them appropriately, etc. With C++ templates, that "cast" is done
at compile time, and saves writing a lot of code.

> And template do not really provide POLYMORPHISM.
> When you write a template, the compiler creates a NEW class for
> each Talkative that you write.
> And those classes have nothing in common a priori, that's why
> example 1 doesn't work !
> If example 2 provides polymorphism, it's not thanks to templates,
> but thanks to the common abstract ancestor - which is much
> comparable to Java interfaces !

Again, I don't really like using the term polymorphism here. Actually,
I think "interface" expresses more what I want, but since that has
specific meaning in Java, it would just confuse the discussion. I
guess the point I want to make is that people are always comparing
Java interfaces to C++ multiple inheritance, often with an array
of abstract base classes (like COM), and decrying the complexity
of this approach. In the last few years C++ compilers have become
so much better at coping with templates, and programmers are
discovering new ways to think about using them to build elegant
solutions. (Now if the syntax could just be made simpler!)

> So we could have Dog and CuckooClock inherit BaseTalkative,
> and throw the templates away...

Watch out, you're letting the Multiple Inheritance Monster poke
its nose into the tent! :-)

Think about the issue of overhead. Once you add a new base class
to the hierarchy, or a new Java interface, you're adding some
burden to every descendant of that class. I'm talking about not
only more byte codes, but also the need to be careful of name
conflicts further down the line, documentation overhead, fatter
interfaces leading to more complex interactions, . . . .

In contrast, a Talkative template doesn't add any overhead to the
other class. All the documentation for Talkative-ness can be
managed in one place, even for the specializations. And there's
a good chance that such minor functionality will be useful only
in a well-defined locality in the code; why let it intrude into
every other place where the class is needed?

> But I still find your idea is great :) Here's why

> > You could argue that adding "implements Talkative" to the class
> > definition is useful for documentation purposes. But you could
> > also argue that it is intrusive on the design of domain classes,
> > and modifying source code which you do not "own" or which others
> > share is sometimes undesirable or impossible for various reasons.
> > ...
> > Even creating a new Java
> > subclass to add Talkative-ness to some domain object can be
> > impossible if most classes are declared final (as is recommended
> > by another article in JavaWorld).

> That's the great point !
> This is a start of solution in the problem of "inheritance insertion"
> which I reaised in another mail on this list !
> You can add (compilation-time) polymorphism to classes with different
> origins, even without having access to their source code.

Everything I read indicates that Java must and will add some kind
of generic-programming ability as it matures. Experience in Ada and
C++ shows that it's too useful to ignore. Reserving the keyword
"generic" is a big hint.

> > If an unrelated (possibly
> > unnoticed because private) talk() function is defined by some
> > class in the hierarchy, overriding that function to implement the
> > Talkative interface could break existing code.

> Nope ! Private methods can be overriden without breaking the code,
> since they are statically linked.

I hadn't realized that. I'll have to study how it works.

> > And there is also
> > the political issue of whether the Talkative subclass should be a
> > member of the same package as its base, or of some other package
> > which you "own."

> Not a real problem : you can actually write classes in packages
> you don't own - even java.lang if you like to !
> I discovered it not so long ago in a Javaworld article ;)
> Create in your package directory a new dir java/lang and add your
> classes into it. You can even use your own version of String or
> Object instead of sun's, but that's another story...

Isn't there a ClassLoader issue that comes into this? But the
main obstacles are political rather than technical. You and six (or
sixty!) other programming teams need to add some minor little interface
to a class that all of you use. Who decides which additions get in?
Who manages the documentation? Who handles change control?

> > To drive into the ground the argument that C++ templates provide
> > even more flexibility than Java interfaces, template classes can
> > also define member variables and additional functionality not
> > related to the class of the template argument.

> Which allows you to attach them to classes which don't have the
> talk() method. But once again, it's only usable at compilation time.

Well, if the Java interface isn't there, things will still fail at
some point. (Although ObjectSpace is doing some very interesting
things with dynamic generation of class byte codes on the fly; check
out our web pages.)

> > They are like
> > interfaces which can be attached to classes for limited purposes
> > and periods of time.

> What is the point of attaching an interface for a limited period of
> time ?

It depends on how necessary the interface is to the life-cycle of
the class. If it's only useful for a limited period of time, why
add a permanent burden?

> > I'm writing to you not to be critical of Java or to start a flame
> > war over religious issues, but simply to point out that there are
> > mechanisms in C++ which work differently from Java, but still
> > work. I think it's more interesting and educational to study the
> > differences between the best mechanisms of different languages,
> > than to look at comparisons where one of the elements is
> > artificial or unidiomatic.

> I fully agree with this.
> I hope you didn't read that mail as a flame !

Not a bit! It's great to have an exchange of ideas. This is
especially since I do most of my work in isolation and have to
depend on email for technical discussions.

> Once again, I like this idea very much since it answers too rarely
> asked questions.

> Pierre-Antoine

Thanks,
Lois






Replies:

Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2009 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us