简体   繁体   English

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

[英]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.

相关问题 如何使用guice自动安装接口的所有实现? - How to auto install all implementations of an interface with guice? Java:填充了接口元素的数据结构 - 如何强制实现接口的类实现compareTo()? - Java: a datastructure filled with interface elements - how to force classes that implement the interface to implement compareTo()? 如何查找 Java 接口的所有实现,而不将它们全部实例化 - How to find all implementations of a Java interface, without instantiating them all 如何使用compareTo()实现比较器 - How to implement Comparator using compareTo() 扩展接口的所有实现的功能? - Extending functionality of all implementations of an Interface? 如何使用 Micronaut 注册和运行单个接口的所有实现? - How to register and run all implementations of a single interface using Micronaut? 如何重构通用方法对接口及其所有实现的返回 - How to refactor the return of a generic method to an interface and all its implementations 如何在classpath中找到所有接口实现? - How can I find all implementations of interface in classpath? 接口的实现必须实现其内部类生成器接口。 怎么做? - Interface's implementations MUST implement its inner class builder interface. How to do it? 如何自动连接具有多个实现的接口 - How to autowire an interface with multiple implementations
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM