用泛型实现接口的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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 02:19:25  来源:igfitidea点击:

Java Abstract Class Implementing an Interface with Generics

javagenericsabstract-class

提问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 SubClasssuch that its instances can only be compared to other SubClassinstances, then how does SubClasssatisfy the contract defined by MyClass? Recall that MyClassis saying that it and any types derived from it can be compared against other MyClassinstances. You're trying to make that not true for SubClass, which means that SubClassdoes not satisfy MyClass's contract: You cannot substitute SubClassfor MyClass, because SubClass's requirements are stricter.

如果您定义某个子SubClass类,使其实例只能与其他SubClass实例进行比较,那么如何SubClass满足由 定义的契约MyClass?回想一下,MyClass它和从它派生的任何类型都可以与其他MyClass实例进行比较。您正在努力使该不是真的SubClass,那该装置SubClass不符合MyClass的契约:你不能代替SubClassMyClass,因为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 的子类型......

SubClassAis 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:

找到了另一个解决方案:

  1. Define an interface on the fields which make up the comaprable (e.g ComparableFoo)
  2. Implement the interface on the parent class
  3. Implement Comparable on the parent class.
  4. Write your implementation.
  1. 在组成comaprable的字段上定义一个接口(例如ComparableFoo)
  2. 在父类上实现接口
  3. 在父类上实现 Comparable。
  4. 写下你的实现。

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 - 这可能不是这种情况,但是你正在编码一个接口并且泛型表达式很简单。