views:

468

answers:

2

I have a base class, say Base which specifies the abstract method deepCopy, and a myriad of subclasses, say A, B, C, ... Z. How can I define deepCopy so that its signature is public X deepCopy() for each class X?

Right, now, I have:

abstract class Base {
  public abstract Base deepCopy();
}

Unfortunately, that means that if if I have an object from a subclass, say a of A, then I always have to perform an unchecked cast for a more specific deep copy:

A aCopy = (A) a.deepCopy();

Is there a way, perhaps using generics, to avoid casting? I want to guarantee that any deep copy returns an object of the same runtime class.

Edit: Let me extend my answer as covariant typing isn't enough. 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 could I avoid the unchecked warning?

+3  A: 

Java 5 supports covariant return types which means that you can implement your deepCopy() method in each subclass to return the specific sub-class instance; e.g.

public class Z extends Base {
  @Override
  public Z deepCopy() {

  }
}

More on covariant return types here.

Adamski
Thanks! I guess you answered my original question, but didn't quite solve my problem. :-)
namin
+2  A: 

This is 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;
 }
}
Tim Bender
+1, this is the only way to specify that a subclass must return an object of its own type.
Andrzej Doyle