[英]How to implement compareTo for all implementations of an interface?
In Java, what is the best approach to provide natural ordering for all implementations of an interface? 在Java中,为接口的所有实现提供自然顺序的最佳方法是什么?
I have an interface, for which I want to ensure/provide natural ordering between all implementations by extending the Comparable
interface: 我有一个接口,我想通过扩展Comparable
接口来确保/提供所有实现之间的自然顺序:
public interface MyInterface extends Comparable<MyInterface> {
}
There will be several implementations of this interface, each of which can define a natural ordering for its own instances, but which may not know how to order itself against other implementations. 该接口将有多种实现,每种实现都可以为其自己的实例定义自然排序,但是可能不知道如何针对其他实现来进行排序。
One approach, which I have used, is to introduce recursive generics and split the natural order comparison by implementation and by instance: 我使用的一种方法是引入递归泛型,并按实现和实例划分自然顺序比较:
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);
}
This means that the implementations of MyInterface
only have to compare between their own instances: 这意味着MyInterface
的实现只需在自己的实例之间进行比较:
public class MyClass implements MyInterface<MyClass> {
public int compare(MyClass other) {
return 0; // ... or something more useful...
}
}
But, recursive generics can become very difficult to maintain. 但是,递归泛型可能变得很难维护。
Is there a better way? 有没有更好的办法?
You could move this casting compare((X) o);
您可以移动此强制转换compare((X) o);
from interface's default method to the implementations and therefore you don't need generic <X extends MyInterface<X>>
at all. 从接口的默认方法到实现,因此您根本不需要泛型<X extends MyInterface<X>>
。
public interface MyInterface extends Comparable<MyInterface> {
@Override
default int compareTo(MyInterface o) {
...
comp = compare(o);
...
}
int compare(MyInterface other);
}
In this case implementations could look like: 在这种情况下,实现可能如下所示:
public class MyClass implements MyInterface {
private Integer property;
public int compare(MyInterface other) {
return Integer.compare(this.property, ((MyClass) other).property);
}
}
So, this is the best I have come up with so far, which kind of blends my original approach with Ruslan's answer and tries to manage the trade offs: 因此,这是到目前为止我能想到的最好的方法,将我的原始方法与Ruslan的答案相结合,并试图权衡取舍:
We define the interface without recursive generics: 我们定义的接口没有递归泛型:
public interface MyInterface extends Comparable<MyInterface> {
@Override // as per the Comparable interface (not needed, but included here for clarity)
int compareTo(MyInterface o);
}
Then we create an abstract class that defines the comparison between implementations, and delegates to the implementations to compare between instances of that implementation. 然后,我们创建一个抽象类,该类定义实现之间的比较,并委托给实现以在该实现的实例之间进行比较。 This improves on having this functionality in the interface, as we limit the scope of the compare()
method to protected
. 由于我们将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);
}
Then in each implementation, we check/cast to that implementation. 然后在每个实现中,我们检查/广播到该实现。 This should never be called with an implementation other than itself, but just to be safe, we throw an IllegalArgumentException
if that were to happen. 切勿使用自身以外的其他实现来调用此方法,但是为了安全起见,如果发生这种情况,我们将抛出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());
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.