Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make java class Comparable to 2 different Classes

I would like to implement the Comparable Interface "Twice"

public class Segment implements Comparable<Segment,Point>{
@Override
public int compareTo(Segment o) {
    return 0;
}
@Override
public int compareTo(Point p) {
    return 0;
}

Is it possible in some way? (Without using the generic interface compareTo(Object o) i think it's nasty...)

like image 401
Duncan De Weireld Avatar asked Sep 17 '25 19:09

Duncan De Weireld


1 Answers

This is not a good idea, as a design pattern. And, by the way, it is impossible in Java, because Comparable and Comparable are the same binary interface due to type erasure.

Anyway, I'll try to explain why I think that's a bad idea. When you implement Comparable you are defining a so-called "natural sorting", which is a sorting intrinsic to the class itself, a natural ordering. This ordering should involve the class and elements of the same class. So, I think (and this is a purely personal opinion) that you should only implement Comparable with the same class as the one you're implementing.

If you want to compare segments with points, this is of course a perfectly legitimate thing, as long as you have a well-defined ordering. You can achieve that by implementing a so-called "external comparator", i.e. a class that implements Comparator<X>, where X is a common superclass of Point and Segment. Java standard classes and functions are prepared to always accept an optional external comparator, because, in general, you might want to have different sorting criteria for objects of the same class.

You seem not to have a common base class/interface. Maybe you should define one, they're both geometrical entities, after all. As of now, the only thing you can do is use Comparator<Object>, and then use the instanceof operator to check the types. Which is a lot of boilerplate code, and also, I think, bad design: since you're saying the points and segments are comparable, they should have some common property that you wish to compare. Then this property should become a method of a common base class or an interface they both implement (which, indeed, might lead you to use Comparable again, but in a cleaner way).

For instance, assume that you want to compare points and segments based on their coordinates, and you want the median of a segment to be considered in sorting. Then, you could do something as:

public abstract class GeometricEntity implements Comparable<GeometricEntity> {
  protected abstract Point getSortingPoint();
  @Override
  public int compareTo(GeometricEntity other) {
    //Compare by getSortingPoint
  }
}

public class Point implements GeometricEntity {
  @Override
  protected Point getSortingPoint() { return this; }
}

public class Segment implements GeometricEntity {
  private Point ptFrom;
  private Point ptTo;
  @Override
  protected Point getSortingPoint() { return meanPoint(ptFrom, ptTo); }
}
like image 115
Giulio Franco Avatar answered Sep 19 '25 07:09

Giulio Franco