Interface with self-referencing generic type

The Comparable interface has a generic type parameter, which is used for self-referencing in subclasses (I don’t know any other use for it) :

public interface Comparable<E> {
  public int compareTo(E other);
}

public class ComparableInteger implements Comparable<ComparableInteger> {
  private int val;
  public void compareTo(ComparableInteger other) {
    return val > other ? 1 : (val == other ? 0 : -1);
}

But what if you need to access methods of the interface on the generic type parameter? Then you can do a recursive declaration of the type parameter. Here is an example, where we have a task object, which can be subclassed in order to do some stuff. Lets say it has a clone method, that should return a copy of itself. Furthermore there is a method on the framework that executes the tasks, which clones the task, let’s say n times and executes them (please note: this example makes no sense, but intentionally):

public interface Task<T extends Task<T>> {
  public T clone();
  public void doWork();
}

public class TaskFramework<T extends Task<T>> {
  public void executeTask(final T task, final int times) {
    for(int i = 0; i < (times); i++) {
      new Thread() {
        public void run() {
          task.clone().doWork();
        }
    }
  }
}

public class ExampleTask extends Task<ExampleTask> {
  private int val;
  public ExampleTask(int val) {
    this.val = val;
  }
  public ExampleTask clone() {
    return new ExampleTask(this.val);
  }
  public doWork() {
    System.out.println("Value: " + val);
  }
  public static void main(String[] args) {
    TaskFramework<ExampleTask> framework = new TaskFramework<ExampleTask>();
    ExampleTask task = new ExampleTask(5);
    framework.executeTask(task, 2);
  }
}

You might like to have a type parameter for the value, too. This would enable you to use the interface Callable for your task and return a value:

public interface Task<T extends Task<T, V>, V> extends Callable<V> {
	public T clone();
	public V call();
}

Leave a Reply

Your email address will not be published. Required fields are marked *