Reputation: 11
I am studying Java because I need it as a prerequirement in one of my college courses. I come from a C++ background, so understanding the logic underlying OOP is not particularly difficult. But there are several differences between the two languages, and one I just cannot figure out is the object cloning feature present in Java. The problem recalls me that of the copy constructor for C++, but the implications are just different.
In Java, there are no destructors and memory is managed by a garbage collector, so there are not the heap memory issues you face in C++. The problem is limited to sharing variables.
Now, reading around, I found that object cloning (unlike copy constructors) is not a feature that an OOP language should provide, as it creates another instance of an object skipping the construction phase. Moreover, clone() cannot manipulate final fields properly, and skip initialization blocks. The same logic behind clonation is "wrong" because "Cloneable" is just like an empty interface, provided only to make a type check in Object.clone(), to raise an exception if the type of the object is not Cloneable.
All the cloning mechanism seems to rely on the Object.clone() method, which allocates memory properly. Each subtype in the class hierarchy supporting clone(), should make a call to "super.clone()" until the Object one is called to allocate all necessary fields. But what happens if a subtype, implementing the Cloneable interface, extends a supertype not doing so? I'm studying from "Arnold, Gosling, Holmes", and one of the defined behaviours towards clone is: "Allow subclasses to support clone but don't publicly support it. Such a class doesn't implement Cloneable, but if the default implementation of clone isn't correct, the class provides a protected clone implementation that clones its fields correctly". This way, calling super.clone(), in the end we will bump into the protected clone() method of the superclass, but such method cannot rely on Object.clone(), because the superclass itself doesn't implement Cloneable. Using the new operator would be an error, because an instance of the superclass would be created, with some missing fields.
So, is supporting clone() (with a protected method) in a non-Cloneable class really useful? And how can one solve the problem of a Cloneable subtype with non-Cloneable supertype?
Upvotes: 1
Views: 131
Reputation: 311
how can one solve the problem of a Cloneable subtype with non-Cloneable super type?
Actually this is not a problem. Think of class Object
: this is a non-Cloneable type, and used as super type of any Cloneable
type. You can create a Cloneable
subtype of any type T. The only thing that matters: is the 'clone' operation implemented correctly for that type T (and its super types). For the class Object
this is will return a field-wise, shallow copy of the original object, with the same class as the original object.
I.e. not every type in the super class thread of a sub class must implement Cloneable
.
... is supporting clone() (with a protected method) in a non-Cloneable class really useful?
Yes. E.g. see the default implementation of clone() in the (non-Cloneable) class Object
.
Upvotes: 0
Reputation: 200296
But what happens if a subtype, implementing the
Cloneable
interface, extends a supertype not doing so?
If it just implements Cloneable
without actually overriding clone()
(yes, that's also possible!), then no harm is done.
If it overrides clone()
and returns an instance which was not retrieved from super.clone()
, then it has broken all its subclasses. This is one of the acknowledged pitfalls of clone()
(covered in Effective Java).
how can one solve the problem of a Cloneable subtype with non-Cloneable supertype?
As explained above, this is not an issue as long as the non-cloneable supertype does not override clone()
(and yes, that's yet another possibility!) or does override it, but in a compliant manner.
Upvotes: 2