Search code examples
javainterfacecomparable

Returning a Comparable from an Interface Method


In Java, one can allow an interface-specified function to return a Comparable simply by using a return type of Comparable. This isn't particularly useful, however, since there's no guarantee that two different implementations of this interface will return Comparables that can be compared to each other. Is there some way of doing this?

To illustrate my question, let's say we're making a class that stores objects and automatically 1) groups them and 2) sorts these groups. So something like:

GroupList.java

public class GroupList<T extends Groupable> {
  private HashMap<Comparable, T[]> data;
  public void add(T e) {
    Comparable group = e.getGroup();
    if(!data.containsKey(group)) { /* make new group for the element */ }
    /* add element to matching group */
  }
  public T[][] get() {
    /* return all the data, with the sets ordered by their Comparable */
  }
}

Groupable.java

public interface Groupable {
  public Comparable getGroup();
}

This runs into the aforementioned problem, however, which means that things like this are possible:

Class A implements Groupable {
  String datestamp;
  public Comparable getGroup() { return datestamp; }
}
Class B implements Groupable {
  Date datestamp;
  public Comparable getGroup() { return datestamp; }
}

This is further complicated by the fact that while all the Comparables must work with each other, I do not know ahead of time what they will be.


Solution

  • You could make the Comparable subclass a generic parameter, too.

    Something like

    public interface Groupable<G extends Comparable<G>> {
      public G getGroup();
    }
    
    public class GroupList<G extends Comparable<G>> {
      private HashMap<G, Groupable<G>[]> data;
      public void add(Groupable<G> e) {
        G group = e.getGroup();
        if(!data.containsKey(group)) { /* make new group for the element */ }
        /* add element to matching group */
      }
      public Groupable<G>[][] get() {
        /* return all the data, with the sets ordered by their Comparable */
      }
    }
    

    In this case, if you have class A implements Groupable<String>, and class B implements Groupable<Date>, you can't mix them in the same GroupList, but you can still mix a different class with the same grouping class, e.g. class C implements Groupable<String>

    GroupList<String> groupList = new GroupList<String>();
    groupList.add(new A()); //ok
    groupList.add(new B()); //compile error
    groupList.add(new C()); //ok