Java抽象类与generics实现接口

我正在试图定义一个实现Comparable的抽象类。 当我用下面的定义来定义类时:

public abstract class MyClass implements Comparable <MyClass> 

子类必须实现compareTo(MyClass object) 。 相反,我希望每个子类都实现compareTo(SubClass object) ,接受它自己types的对象。 当我尝试用类似下面的方法定义抽象类时:

 public abstract class MyClass implements Comparable <? extends MyClass> 

它抱怨说“超types可能不指定任何通配符”。

有解决scheme吗?

这在我看来有点过于冗长,但是起作用了:

 public abstract class MyClass<T extends MyClass<T>> implements Comparable<T> { } public class SubClass extends MyClass<SubClass> { @Override public int compareTo(SubClass o) { // TODO Auto-generated method stub return 0; } } 

除了遇到声明签名的机械困难之外,目标没有什么意义。 你正试图build立一个协变比较函数,这个函数打破了build立派生类可以定制的接口的想法。

如果您定义一些子类SubClass ,使其实例只能与其他SubClass实例进行比较,那么SubClass如何满足由MyClass定义的协定? 回想一下, MyClass是说,它和从它派生的任何types都可以与其他MyClass实例进行比较。 您试图使SubClass不正确,这意味着SubClass不满足MyClass的合同:您不能将SubClassreplace为MyClass ,因为SubClass的要求更严格。

这个问题集中在协变和逆变,以及它们如何通过types派生允许函数签名改变。 您可以放宽参数types的要求 – 接受比超types的签名要求更宽的types – 您可以加强对返回types的要求 – 承诺返回比超types签名更窄的types。 这些自由中的每一个仍然允许对超types的派生types进行完美的replace; 当通过超types的接口使用派生types时,调用者无法区分差异,但具体使用派生types的调用者可以利用这些自由。

Willi的答案讲授了关于generics声明的一些东西,但是我希望你在接受这个技术之前重新考虑你的目标,而牺牲语义。

看Java自己的例子:

 public abstract class Enum<E extends Enum<E>> implements Comparable<E> public final int compareTo(E o) 

对此评论:通常这个论点是正确的。 但generics使得types关系更加复杂。 在Willi的解决scheme中,SubClass可能不是MyClass的子types….

SubClassAMyClass<SubClassA>的子types,但不是MyClass<SubClassB>的子types

typesMyClass<X>为其所有子types必须遵守的compareTo(X)定义一个契约。 那里没有问题。

我不确定你需要捕捉:

首先,将compareTo添加到抽象类…

 public abstract class MyClass implements Comparable <MyClass> { @Override public int compareTo(MyClass c) { ... } } 

然后添加实现…

 public class MyClass1 extends MyClass { ... } public class MyClass2 extends MyClass { ... } 

调用比较将调用超types的方法…

 MyClass1 c1 = new MyClass1(); MyClass2 c2 = new MyClass2(); c1.compareTo(c2); 
 public abstract class MyClass<T> implements Comparable<T> { } public class SubClass extends MyClass<SubClass> { @Override public int compareTo(SubClass o) { // TODO Auto-generated method stub return 0; } } 

find另一个解

  1. 在组成可合作的字段上定义一个接口(如ComparableFoo)
  2. 实现父类的接口
  3. 在父类上实现Comparable。
  4. 编写你的实现。

解决scheme应该是这样的:

 public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> { public int compareTo(ComparableFoo o) { // your implementation } } 

这个解决scheme意味着更多的事情可能会实现ComparableFoo – 这可能不是这种情况,但是你编码到一个接口,genericsexpression式很简单。

我知道你说你想要“compareTo(SubClass对象),接受它自己的types的对象”,但我仍然build议声明这样的抽象类:

 public abstract class MyClass implements Comparable <Object> 

在覆盖MySubClass中的compareTo时做一个instanceof检查:

 @Override public int compareTo(Object o) { if (o instanceof MySubClass)) { ... } else throw new IllegalArgumentException(...) } 

类似于“等于”或“克隆”