Java抽象类用泛型实现接口

Cem*_*Cem 64 java generics abstract-class

我正在尝试定义一个实现Comparable的抽象类.当我使用以下定义定义类时:

public abstract class MyClass implements Comparable <MyClass>
Run Code Online (Sandbox Code Playgroud)

子类必须实现compareTo(MyClass object).相反,我希望每个子类都能实现compareTo(SubClass object),接受自己类型的对象.当我尝试使用以下内容定义抽象类时:

public abstract class MyClass implements Comparable <? extends MyClass>
Run Code Online (Sandbox Code Playgroud)

它抱怨说"超类型可能没有指定任何通配符".

有解决方案吗?

whi*_*rra 44

在我看来,它有点过于冗长,但有效:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

  • `public abstract class MyClass <T>实现Comparable <T>`同样好 (3认同)
  • 考虑(1)类MyImpl1扩展MyClass <MyImpl1> {...}; (2)类MyImpl2扩展MyClass <MyImpl1> {public int compareTo(MyImpl1 o){...}}.MyImpl2做得不对. (2认同)
  • 如果我们假设每个子类都使用自己的类作为泛型参数扩展 MyClass,则解决方案是正确的。然而,正如埃默里指出的那样,似乎没有办法确保这一点。 (2认同)

seh*_*seh 19

除了你在宣布签名时遇到的机械困难之外,目标没有多大意义.您正在尝试建立一个协变比较函数,它打破了建立派生类可以定制的接口的整个想法.

如果你定义一些子SubClass类使得它的实例只能与其他SubClass实例进行比较,那么如何SubClass满足由MyClass?定义的契约呢?回想一下,MyClass它可以说它和从它派生的任何类型都可以与其他MyClass实例进行比较.你想做出不正确的SubClass,这意味着SubClass不满足MyClass的合同:你不能代替SubClassMyClass,因为SubClass的要求是严格的.

这个问题集中在协方差和逆变,以及它们如何允许函数签名通过类型派生来改变.您可以放宽对参数类型的要求 - 接受比超类型的签名要求更宽泛的类型 - 并且您可以增强对返回类型的要求 - 承诺返回比超类型签名更窄的类型.这些自由中的每一个仍然允许完全替换派生类型的超类型; 当通过超类型的接口使用派生类型时,调用者无法区分,但是具体使用派生类型的调用者可以利用这些自由.

Willi的回答讲述了关于泛型声明的一些内容,但我建议您在以语义为代价接受该技术之前重新考虑您的目标.

  • 我看到的另一个问题是将子类对象存储在Collection中.我应该能够用`List <MyClass>`而不是`List <MyClass <?>>`来存储它们.当你得到其中一个对象并调用`equals(anObject)`时会被调用什么? (2认同)