The Artima Developer Community
Sponsored Link

Java Design Issues
A Conversation with Ken Arnold, Part VI
by Bill Venners
October 14, 2002

<<  Page 4 of 5  >>


Bill Venners: So I'm writing a class today and I want to make it easy to clone or copy. What do I do?

Ken Arnold: If you are writing a class today, you have only a few reasonable interaction patterns. One is to go all the way. You implement the clone method; you declare it public, without throwing a CloneNotSupportedException if possible; and you implement clone. I say "if possible" because you may have to be able to throw CloneNotSupportedException. The clone method of the container classes, for example, needs to be able to throw CloneNotSupportedException, because although the container might be Cloneable, the objects it references might not be.

There is also a question of deep versus shallow copies. Do you want to copy the contents, or just the collection that refers to the same underlying objects? A shallow copy would give you two collections, each of which refers to the same underlying objects, rather than referring to new underlying objects. If your clone is deep, you might still have to allow CloneNotSupportedException in your clone method.

Another approach, which I don't prefer, is to pretend clone and Cloneable don't exist. However, you can't do that in industrial-strength classes. In industrial-strength classes, you would either make clone public, without throwing the exception if you can avoid it. Or you implement clone so that it will work if invoked, but you let each subclass decide if it should be public. Or you override clone with something that throws CloneNotSupportedException; in effect, stating you cannot clone this even in subclasses. The problem with ignoring clone is that nothing can stop a subclass from making it public and indirectly invoking your clone method. Then, if your clone method is inherited from Object -- in other words, if you have never written one -- and Object's clone implementation does the wrong thing, the user will have a corrupt class. It is better to notify users of that with CloneNotSupportedException. So in industrial-strength classes, I would pick one of these approaches. There is also this weird, almost surreal, approach where you can implement Cloneable and not make your clone method public, but I think you should never do that.

Bill Venners: So what about copy constructors? Do they have a time and place?

Ken Arnold: I am not fond of copy constructors. In fact, I'm not very fond of constructors at all. The problem is that the code that creates the object with a constructor is defining the object's type. In all other operations, the code that uses an object effectively only defines that the object is at least a certain type. Constructors are an exception to that rule. I don't think that exception should exist.

You can also think of it this way: new Foo should turn into an invocation of a static method that might create a subclass. The static method could look at the parameters and say: I will create a Foo subclass that is efficient for these kinds of parameters. At the point where you want a Foo, there are myriad reasons why the implementer of Foo may know you want a subclass, but you don't know it. And maybe you shouldn't know it, because next week a different set of decisions might make sense. The actual class of object that gets created is an implementation detail. You need something that is at least a Foo. You should go to the Foo class and say: I need something that is at least what you are, and here are the initialization parameters. Other languages will do that; of all things, Perl objects do that. I think this is a better solution. By calling a copy constructor on Foo, you are asking the Foo class to get a copy of this object that is at least a Foo, which is not the Foo class's business.

<<  Page 4 of 5  >>

Sponsored Links

Copyright © 1996-2018 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use