用泛型实现接口的Java抽象类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3592939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Abstract Class Implementing an Interface with Generics
提问by Cem
I am trying to define an abstract class implementing Comparable. When I define the class with following definition:
我正在尝试定义一个实现 Comparable 的抽象类。当我使用以下定义定义类时:
public abstract class MyClass implements Comparable <MyClass>
subclasses have to implement compareTo(MyClass object)
. Instead, I want every subclass to implement compareTo(SubClass object)
, accepting an object of its own type. When I try to define the abstract class with something like:
子类必须实现compareTo(MyClass object)
. 相反,我希望每个子类都实现compareTo(SubClass object)
,接受它自己类型的对象。当我尝试使用以下内容定义抽象类时:
public abstract class MyClass implements Comparable <? extends MyClass>
It complains that "A supertype may not specify any wildcard."
它抱怨“超类型可能没有指定任何通配符”。
Is there a solution?
有解决办法吗?
采纳答案by whiskeysierra
It's a little too verbose in my opinion, but works:
在我看来,这有点过于冗长,但有效:
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;
}
}
回答by zevra0
I'm not sure that you need the capture:
我不确定您是否需要捕获:
First, add the compareTo to the abstract class...
首先,将 compareTo 添加到抽象类...
public abstract class MyClass implements Comparable <MyClass> {
@Override
public int compareTo(MyClass c) {
...
}
}
Then add the implementations...
然后添加实现...
public class MyClass1 extends MyClass {
...
}
public class MyClass2 extends MyClass {
...
}
Calling compare will call the super type method...
调用 compare 将调用超类型方法...
MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();
c1.compareTo(c2);
回答by seh
Apart from the mechanical difficulties you're encountering declaring the signatures, the goal doesn't make much sense. You're trying to establish a covariant comparison function, which breaks the whole idea of establishing an interface that derived classes can tailor.
除了你在声明签名时遇到的机械困难之外,这个目标没有多大意义。您正在尝试建立一个协变比较函数,这打破了建立派生类可以定制的接口的整个想法。
If you define some subclass SubClass
such that its instances can only be compared to other SubClass
instances, then how does SubClass
satisfy the contract defined by MyClass
? Recall that MyClass
is saying that it and any types derived from it can be compared against other MyClass
instances. You're trying to make that not true for SubClass
, which means that SubClass
does not satisfy MyClass
's contract: You cannot substitute SubClass
for MyClass
, because SubClass
's requirements are stricter.
如果您定义某个子SubClass
类,使其实例只能与其他SubClass
实例进行比较,那么如何SubClass
满足由 定义的契约MyClass
?回想一下,MyClass
它和从它派生的任何类型都可以与其他MyClass
实例进行比较。您正在努力使该不是真的SubClass
,那该装置SubClass
不符合MyClass
的契约:你不能代替SubClass
的MyClass
,因为SubClass
的要求是严格的。
This problem centers on covariance and contravariance, and how they allow function signatures to change through type derivation. You can relaxa requirement on an argument's type—accepting a wider type than the supertype's signature demands—and you can strengthena requirement on a return type—promising to return a narrower type than the supertype's signature. Each of these freedoms still allows perfect substitution of the derived type for the supertype; a caller can't tell the difference when using the derived type through the supertype's interface, but a caller using the derived type concretely can take advantage of these freedoms.
这个问题集中在协方差和逆变,以及它们如何允许函数签名通过类型派生改变。你可以放宽对参数类型的要求——接受比超类型签名要求更宽的类型——并且你可以加强对返回类型的要求——承诺返回比超类型签名更窄的类型。这些自由中的每一个仍然允许将派生类型完美替换为超类型;当通过超类型的接口使用派生类型时,调用者无法区分,但具体使用派生类型的调用者可以利用这些自由。
Willi's answerteaches something about generic declarations, but I urge you to reconsider your goal before accepting the technique at the expense of semantics.
Willi 的回答教了一些关于泛型声明的知识,但我敦促您在接受该技术之前重新考虑您的目标,而以牺牲语义为代价。
回答by irreputable
see Java's own example:
看Java自己的例子:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>
public final int compareTo(E o)
on seh's comment: usually the argument is correct. but generics makes type relations more complicated. a SubClass may not be a subtype of MyClass in Willi's solution....
关于 seh 的评论:通常这个论点是正确的。但是泛型使类型关系更加复杂。在 Willi 的解决方案中,子类可能不是 MyClass 的子类型......
SubClassA
is a subtype of MyClass<SubClassA>
, but not a subtype of MyClass<SubClassB>
SubClassA
是 的子类型MyClass<SubClassA>
,但不是 的子类型MyClass<SubClassB>
type MyClass<X>
defines a contract for compareTo(X)
which all of its subtypes must honor. there is no problem there.
typeMyClass<X>
定义了一个契约,compareTo(X)
它的所有子类型都必须遵守。没有问题。
回答by newacct
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;
}
}
回答by Caroline Even
I know you said you want "compareTo(SubClass object), accepting an object of its own type", but I still suggest declaring the abstract class like this:
我知道你说你想要“compareTo(SubClass object), accepting an object of its own type”,但我仍然建议像这样声明抽象类:
public abstract class MyClass implements Comparable <Object>
and do an instanceof check when overriding compareTo in MySubClass:
并在 MySubClass 中覆盖 compareTo 时执行 instanceof 检查:
@Override
public int compareTo(Object o) {
if (o instanceof MySubClass)) {
...
}
else throw new IllegalArgumentException(...)
}
similarly to 'equals' or 'clone'
类似于“等于”或“克隆”
回答by David Levy
Found another solution:
找到了另一个解决方案:
- Define an interface on the fields which make up the comaprable (e.g ComparableFoo)
- Implement the interface on the parent class
- Implement Comparable on the parent class.
- Write your implementation.
- 在组成comaprable的字段上定义一个接口(例如ComparableFoo)
- 在父类上实现接口
- 在父类上实现 Comparable。
- 写下你的实现。
Solution should look like this:
解决方案应如下所示:
public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> {
public int compareTo(ComparableFoo o) {
// your implementation
}
}
This solution implies that more things might implement ComparableFoo - this is likely not the case but then you're coding to an interface and the generics expression is simple.
这个解决方案意味着更多的东西可能会实现 ComparableFoo - 这可能不是这种情况,但是你正在编码一个接口并且泛型表达式很简单。