Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using generics to implement a common method in an abstract class

Tags:

java

generics

Let's say I have this hierarchy:

public abstract class AbstractEntity implements Cloneable {
    ...
    public AbstractEntity clone() {
        Cloner cloner = new Cloner();
        AbstractEntity cloned = cloner.deepClone(this);
        return cloned;
    }
}

public class EntityA extends AbstractEntity {
    ...
}

This works fine, I can do:

EntityA e1 = new EntityA();
EntityA e2 = (EntityA) e1.clone();

but I have to do a manual typecast. Is there a way to use java Generics in order to have the clone() method return the actual type of the subclass?

Thank you!

like image 909
yankee Avatar asked Feb 07 '13 17:02

yankee


2 Answers

The closest I can think of would be something like:

public abstract class AbstractEntity<T extends AbstractEntity<T>> 
    implements Cloneable {

    @SuppressWarnings("unchecked")
    public T clone() {
        Cloner cloner = new Cloner();
        T cloned = (T) cloner.deepClone(this);
        return cloned;
    }    
}

public class EntityA extends AbstractEntity<EntityA> { 
    ...
}

public class EntityB extends AbstractEntity<EntityB> { 
    ...
}

It's not entirely safe: you could write:

public class EvilClass extends AbstractEntity<EntityA> { 
    ...
}

... but whether or not that's important to you depends on your use case.

like image 110
Jon Skeet Avatar answered Sep 30 '22 01:09

Jon Skeet


I don't think generics are needed. You can declare a clone() method in the abstract class, and override it to return a subclass in the subclass.

package inheritance;

public abstract class AbstractEntity {

    public abstract AbstractEntity clone();
}


package inheritance;

public class ClassA extends AbstractEntity {

    @Override
    public ClassA clone() { return null; }

}


package inheritance;

public class Driver {

    /**
     * @param args
     */
    public static void main(String[] args) {
        ClassA a = new ClassA();
        ClassA b = a.clone();
        System.out.println("all done");
    }

}

Isn't that what you wanted to do?

like image 36
arcy Avatar answered Oct 03 '22 01:10

arcy