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
的合同:您不能将SubClass
replace为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….
SubClassA
是MyClass<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另一个解
- 在组成可合作的字段上定义一个接口(如ComparableFoo)
- 实现父类的接口
- 在父类上实现Comparable。
- 编写你的实现。
解决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(...) }
类似于“等于”或“克隆”