How to implement generic deep type cloning in a Java class hierarchy?
I have a base class, for example Base
, which indicates an abstract method deepCopy
and many subclasses, eg A
, B
, C
, ... Z
. How to define deepCopy
so that its signature public X deepCopy()
for each class X
?
Now I have:
abstract class Base {
public abstract Base deepCopy();
}
Unfortunately, this means that if I have an object from a subclass, say A
of A
, then I always need to do an unchecked cast for a more specific deep copy:
A aCopy = (A) a.deepCopy();
Is there a way, perhaps to use generics to avoid casting? I want to ensure that any deep copy returns an object of the same runtime class.
Edit: Let me extend my answer since covariant input is not enough. Let's say I then wanted to implement a method like:
static <N extends Base> List<N> copyNodes(List<N> nodes) {
List<N> list = Lists.newArrayList();
for (N node : nodes) {
@SuppressWarnings("unchecked")
N copy = (N) node.deepCopy();
list.add(copy);
}
return list;
}
How can I avoid the unverified warning?
source to share
It's really not pretty, and I probably wouldn't do it myself, but:
public abstract class Base<T extends Base<T>> {
public abstract T deepCopy();
}
public class Extender extends Base<Extender> {
@Override
public Extender deepCopy() {
// TODO Auto-generated method stub
return null;
}
}
Or....
public abstract class Base<T extends Base<T>> {
public abstract T deepCopy();
}
public class Extender<T extends Base<T>> extends Base<T> {
@Override
public T deepCopy() {
// TODO Auto-generated method stub
return null;
}
}
source to share
What about...
public interface DeeplyCloneable <T extends Cloneable> {
public T deepClone();
}
Then ... for example ... (erroneous but well-intentioned, help!)
public class DeeplyClonableHashTable
<T1 extends DeeplyCloneable<?>,T2 extends DeeplyCloneable<?>>
extends Hashtable<T1,T2>
implements DeeplyCloneable<Hashtable<T1,T2>>{
@Override
public Hashtable<T1, T2> deepClone() {
Object o = super.clone();
if ((o == null) || (! (o instanceof DeeplyClonableHashTable<?,?>)))
{
throw new DeepCloneException(
"Object instance does not support deepCloneing.");
}
@SuppressWarnings("unchecked")
DeeplyClonableHashTable<T1,T2> copy = (DeeplyClonableHashTable<T1,T2>)o;
Set<T1> keys = copy.keySet();
for (T1 key: keys){
T2 value = this.get(key);
T1 keyCopy = key.deepClone(); // this line is in error
T2 valueCopy = value.deepClone(); // this line is in error
copy.put(keyCopy, valueCopy);
}
return copy;
}
}
source to share