在Java中,为接口的所有实现提供自然顺序的最佳方法是什么?
我有一个接口,我想通过扩展Comparable
接口来确保/提供所有实现之间的自然顺序:
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...
}
}
但是,递归泛型可能变得很难维护。
有更好的方法吗?
答案 0 :(得分:2)
您可以将此强制转换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);
}
}
答案 1 :(得分:1)
因此,这是到目前为止我能想到的最好的方法,它将我的原始方法与Ruslan's answer融合在一起,并试图权衡取舍:
我们定义了没有递归泛型的接口:
public interface MyInterface extends Comparable<MyInterface> {
@Override // as per the Comparable interface (not needed, but included here for clarity)
int compareTo(MyInterface o);
}
然后,我们创建一个抽象类,该抽象类定义实现之间的比较,并委托给实现以在该实现的实例之间进行比较。由于我们将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);
}
然后在每个实现中,我们检查/投射到该实现。绝对不要使用其他实现来调用它,但是为了安全起见,如果发生这种情况,我们将抛出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());
}
}
}