如何为接口的所有实现实现 compareTo?

How to implement compareTo for all implementations of an interface?

在 Java 中,为接口的所有实现提供自然排序的最佳方法是什么?

我有一个接口,我想通过扩展 Comparable 接口在所有实现之间 ensure/provide 自然排序:

public interface MyInterface extends Comparable<MyInterface> {

}

此接口将有多个实现,每个实现都可以为自己的实例定义自然顺序,但可能不知道如何根据其他实现对自己进行排序。

我使用的一种方法是引入递归泛型并按实现和实例拆分自然顺序比较:

public interface MyInterface<X extends MyInterface<X>> extends Comparable<MyInterface> {

  @Override
  default int compareTo(MyInterface o) {
    // the interface defines how to compare between implementations, say...
    int comp = this.getClass().getSimpleName().compareTo(o.getClass().getSimpleName());
    if (comp == 0) {
      // but delegates to compare between instances of the same implementation
      comp = compare((X) o);
    }
    return comp;
  }

  int compare(X other);
}

这意味着 MyInterface 的实现只需要在它们自己的实例之间进行比较:

public class MyClass implements MyInterface<MyClass> {

  public int compare(MyClass other) {
    return 0; // ... or something more useful... 
  }
}

但是,递归泛型可能变得非常难以维护。

有没有更好的方法?

您可以将此转换 compare((X) o); 从接口的默认方法移动到实现,因此您根本不需要通用 <X extends MyInterface<X>>

public interface MyInterface extends Comparable<MyInterface> {
    @Override
    default int compareTo(MyInterface o) {
        ...
        comp = compare(o);
        ...
    }
    int compare(MyInterface other);
}

在这种情况下,实现可能如下所示:

public class MyClass implements MyInterface {
    private Integer property;
    public int compare(MyInterface other) {
        return Integer.compare(this.property, ((MyClass) other).property);
    }
}

所以,这是迄今为止我想出的最好的方法,它融合了我原来的方法与 并试图权衡取舍:

我们定义接口没有递归泛型:

public interface MyInterface extends Comparable<MyInterface> {

  @Override // as per the Comparable interface (not needed, but included here for clarity)
  int compareTo(MyInterface o);
}

然后我们创建一个抽象 class 来定义实现之间的比较,并委托实现来比较该实现的实例。这改进了在界面中具有此功能,因为我们将 compare() 方法的范围限制为 protected.

public abstract class MyAbstractClass implements MyInterface {

  @Override
  public int compareTo(MyInterface o) {
    // the interface defines how to compare between implementations, say...
    int comp = this.getClass().getSimpleName().compareTo(o.getClass().getSimpleName());
    if (comp == 0) {
      // but delegates to compare between instances of the same implementation
      comp = compare(o);
    }
    return comp;
  }

  protected abstract int compare(MyInterface other);
}

然后在每个实现中,我们 check/cast 到那个实现。永远不应使用除自身以外的实现来调用它,但为了安全起见,如果发生这种情况,我们将抛出一个 IllegalArgumentException

public class MyClass implements MyInterface {

  public int compare(MyClass o) {
    if (o instanceof MyClass) {
      return 0; // ... or something more useful... 
    } else {
      throw new IllegalArgumentException("Cannot compare " + this.getClass() + " with " + o.getClass());
    }
  }
}