Java 抽象类使用泛型实现接口
我试图定义一个实现 Comparable 的抽象类。当我使用以下定义定义类时:
public abstract class MyClass implements Comparable <MyClass>
子类必须实现compareTo(MyClass object)。相反,我希望每个子类都实现compareTo(SubClass object),接受其自己类型的对象。当我尝试用以下内容定义抽象类时:
public abstract class MyClass implements Comparable <? extends MyClass>
它抱怨“超类型可能未指定任何通配符”。
有解决办法吗?
I am trying to define an abstract class implementing Comparable. When I define the class with following definition:
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:
public abstract class MyClass implements Comparable <? extends MyClass>
It complains that "A supertype may not specify any wildcard."
Is there a solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
在我看来,这有点太冗长了,但是有效:
It's a little too verbose in my opinion, but works:
除了声明签名时遇到的机械困难之外,这个目标没有多大意义。您正在尝试建立一个协变比较函数,这打破了建立派生类可以定制的接口的整个想法。
如果您定义了一些子类
SubClass
,使其实例只能与其他SubClass
实例进行比较,那么SubClass
如何满足SubClass
定义的契约代码>我的类?回想一下,MyClass
表示它以及从它派生的任何类型都可以与其他MyClass
实例进行比较。您试图使SubClass
不成立,这意味着SubClass
不满足MyClass
的合同:您不能替换SubClass
为MyClass
,因为SubClass
的要求更严格。这个问题集中在协变和逆变,以及它们如何允许函数签名通过类型推导而改变。您可以放宽对参数类型的要求 - 接受比超类型签名要求更宽的类型 - 并且您可以加强对返回类型的要求 - 承诺返回更窄的类型类型而不是超类型的签名。这些自由中的每一个仍然允许派生类型完美地替换超类型;通过超类型的接口使用派生类型时,调用者无法区分,但具体使用派生类型的调用者可以利用这些自由。
Willi 的回答教授了一些有关泛型声明的内容,但我敦促您在接受以牺牲语义为代价的技术之前重新考虑您的目标。
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 otherSubClass
instances, then how doesSubClass
satisfy the contract defined byMyClass
? Recall thatMyClass
is saying that it and any types derived from it can be compared against otherMyClass
instances. You're trying to make that not true forSubClass
, which means thatSubClass
does not satisfyMyClass
's contract: You cannot substituteSubClass
forMyClass
, becauseSubClass
's requirements are stricter.This problem centers on covariance and contravariance, and how they allow function signatures to change through type derivation. You can relax a requirement on an argument's type—accepting a wider type than the supertype's signature demands—and you can strengthen a 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 answer teaches something about generic declarations, but I urge you to reconsider your goal before accepting the technique at the expense of semantics.
请参阅Java自己的示例:
关于seh的评论:通常该参数是正确的。但泛型使类型关系变得更加复杂。在 Willi 的解决方案中,SubClass 可能不是 MyClass 的子类型...
SubClassA
是MyClass
的子类型,但不是MyClass
的子类型SubClassB>
类型
MyClass
定义了compareTo(X)
的契约,其所有子类型都必须遵守该契约。那里没有问题。see Java's own example:
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....
SubClassA
is a subtype ofMyClass<SubClassA>
, but not a subtype ofMyClass<SubClassB>
type
MyClass<X>
defines a contract forcompareTo(X)
which all of its subtypes must honor. there is no problem there.我不确定您是否需要捕获:
首先,将compareTo添加到抽象类...
然后添加实现...
调用compare将调用超类型方法...
I'm not sure that you need the capture:
First, add the compareTo to the abstract class...
Then add the implementations...
Calling compare will call the super type method...
找到了另一个解决方案:
解决方案应该如下所示:
该解决方案意味着更多的东西可能会实现 ComparableFoo - 情况可能并非如此,但是您正在对接口进行编码,并且泛型表达式很简单。
Found another solution:
Solution should look like this:
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.
我知道你说你想要“compareTo(SubClass object),接受它自己类型的对象”,但我仍然建议像这样声明抽象类:
并在覆盖 MySubClass 中的compareTo时进行instanceof检查:
类似于“equals”或'克隆'
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:
and do an instanceof check when overriding compareTo in MySubClass:
similarly to 'equals' or 'clone'