If you have an OO language, where every object always has a copy method, shouldn't that be deep copy by default?
In most languages I know, such a copy method is shallow, since a shallow copy is more lightweight, of course. It's faster, it requires less memory, and it's quite often sufficient. And when you ask for deep copy the typical answer is: Just write your own one if you require one.
But IMHO there is a logic flaw in the last sentence. To write a deep copy for any object type, I need to know that exact object type. I don't need to know the object type when calling
copy, as that's a universal method that all objects offer.
So when I have an object of unknown type,
Object o, I cannot know if that object references other objects or not, so I cannot know if I'd even need a deep copy for that object or not. How would I write a deep copy for it? I know that this object has a
copy method, but I cannot know if that copy is sufficient to freeze the state of that object or if a deep copy would be required.
So why would I want just a shallow copy? I want a shallow copy, when I know that an object may reference other objects and those other objects may change but I don't care if they do or I even want to change them myself and have that change reflected to whoever else references these objects. But when that case arises, I will usually know the type of the object and then I could implement a shallow copy for it or the object itself could offer one.
Let's take an object like
Array for example. An array references other objects. If I just get an
Object o, I cannot know if that
o is an array (well, I can test for it but then I have to test for all existing container classes). If I make a copy of it and pass that copy to some method which will know that this object is an array and access its element and performs operations according to their state, I expect that when I later on pass the same copy to the same method, it will behave exactly the same but that isn't guaranteed, as the objects the array references may have changed, despite me having never changed them in my code. So I have a copy but that copy may change on its own. How could I avoid that? I cannot, since I cannot implement a deep copy for
Object or start testing for all known container classes and implement deep copies for each of them.
On the other hand, if
copy is always deep, I don't need to know the type of
o, I can just call
copy on it and get a deep copy for sure that is frozen in time and will never change, unless I change it or expose that copy to other code that could change it.
So when would I want a shallow copy of an array? Usually only, when I know that this is an array and I just want to preserve references to the objects it contains yet don't mind if those objects themselves do change. But in that case I don't have to call
copy, I can instead write a simple shallow copy or use something like a copy constructor or if that doesn't exist, I can usually do something like
newArray = new Array()
Shallow copies are usually desired in situations where the object type is known and not when it is unknown and most objects provide an interface that makes a shallow copy easy to perform. It doesn't seem very likely to me that I have an object of unknown type and know for sure, that a shallow copy will do the trick. What situation would that be? Unless I know the type, I cannot know if a shallow copy is safe and if in doubt, a deep copy is the safer copy.
And as for having two copy method for every object,
deepCopy, again, how would you know when to call which one? You cannot decide that unless you know the type of object you are dealing with, can you? And if you know that type, a copy constructor that is documented to be shallow would do, wouldn't it?
Is my logic flawed? Shouldn't the default always be optimized for safety and not for performance? Isn't optimizing copy for speed premature optimization?