This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I was wondering, first of all, why clone() is not implemented automatically from the root object class and why most clone() operations are a shallow clone and not a deep clone. And how do I create a deep clone method for a class I wrote? Thanks...
Well... I am only guessing, so hopefully someone more skilled in Java like Mr. Friedman-Hill can instruct us. But I would guess this.
a) First of all, class Object actually implements a protected clone() method. This method uses reflection to create a new instance and then do a shallow copy. However, the method checks whether the subtype to be cloned is actually "Cloneable", and if not it throws an exception.
Why would we want this? Well, my best guess is that we don't want all possible Java objects to be cloneable. This would make it impossible to control the number of instances of a given type (a la Singleton Pattern). Other times, it might make it confusing when you have some one-to-one relationship between a object and another (like an object that is backed by a database or something). Cloning such an object would lead to unexpected behaviours, which we might want to avoid.
So I think the idea is that by tagging your class with "Cloneable", you are guaranteeing that your class is safe to be cloned, so you might even want to create a public clone() method that calls Object's clone() by a waterfall of super.clone() calls.
I've heard many people recommend not to use this because it's not very well documented and relies on many conventions...
b) Why deep and not shallow? Well... there are several considerations that you would need to keep in mind if you wanted to implement a deep copy. First of all, all fields of a class would require to be Cloneable (see a). This might or might not be something we have.
Additionally, suppose we have two fields pointing to the same place... if we call clone on each field, we will end up having each field pointing at different places.
In general, the problem of a generalized method for deep copying would have to make some assumptions that might or might not hold for ADTs that are even a bit complicated. For that reason, I guess it's just easier to implement shallow copy (which is what most people need anyways).
Once more, I'm not really sure about this, so take what I said with a grain of salt.
clone() is a feature of Java from the earliest versions of the language. It is one that has not stood the test of time well. There are many things less than ideal about how the clone() feature of the language was designed.
It remains necessary to use clone() for arrays, as the alternative of coding your own array-duplicating code would be inefficient. Certain Java and third-party APIs also depend on clone().
Apart from the above situations, my suggestion would be that, when you want an method to copy an object of one of your classes, you write your own method, without using clone(). Your method can do shallow or deep copying (or something in between), as required by your particular application.
Betty Rubble? Well, I would go with Betty... but I'd be thinking of Wilma.