Java 抽象类使用泛型实现接口

发布于 2024-09-16 09:09:42 字数 396 浏览 4 评论 0原文

我试图定义一个实现 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

南巷近海 2024-09-23 09:09:42

在我看来,这有点太冗长了,但是有效:

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

}

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

}
下雨或天晴 2024-09-23 09:09:42

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

如果您定义了一些子类 SubClass ,使其实例只能与其他 SubClass 实例进行比较,那么 SubClass 如何满足 SubClass 定义的契约代码>我的类?回想一下,MyClass 表示它以及从它派生的任何类型都可以与其他 MyClass 实例进行比较。您试图使 SubClass 不成立,这意味着 SubClass 不满足 MyClass 的合同:您不能替换 SubClassMyClass,因为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 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.

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.

智商已欠费 2024-09-23 09:09:42

请参阅Java自己的示例:

public abstract class Enum<E extends Enum<E>> implements Comparable<E>
    public final int compareTo(E o)

关于seh的评论:通常该参数是正确的。但泛型使类型关系变得更加复杂。在 Willi 的解决方案中,SubClass 可能不是 MyClass 的子类型...

SubClassAMyClass 的子类型,但不是 MyClass的子类型SubClassB>

类型 MyClass 定义了 compareTo(X) 的契约,其所有子类型都必须遵守该契约。那里没有问题。

see Java's own example:

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....

SubClassA is a subtype of MyClass<SubClassA>, but not a subtype of MyClass<SubClassB>

type MyClass<X> defines a contract for compareTo(X) which all of its subtypes must honor. there is no problem there.

奈何桥上唱咆哮 2024-09-23 09:09:42

我不确定您是否需要捕获:

首先,将compareTo添加到抽象类...

public abstract class MyClass implements Comparable <MyClass> {

@Override
public int compareTo(MyClass c) {
...
}    
}

然后添加实现...

public class MyClass1 extends MyClass {
...
}

public class MyClass2 extends MyClass {
...
}

调用compare将调用超类型方法...

MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();

c1.compareTo(c2);

I'm not sure that you need the capture:

First, add the compareTo to the abstract class...

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...

MyClass1 c1 = new MyClass1();
MyClass2 c2 = new MyClass2();

c1.compareTo(c2);
荒芜了季节 2024-09-23 09:09:42
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;
    }

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

}
著墨染雨君画夕 2024-09-23 09:09:42

找到了另一个解决方案:

  1. 在构成可映射的字段上定义一个接口(例如ComparableFoo)
  2. 在父类上实现该接口
  3. 在父类上实现Comparable。
  4. 写下你的实现。

解决方案应该如下所示:

public abstract class MyClass implements ComparableFoo,Comparable<ComparableFoo> {
    public int compareTo(ComparableFoo o) {
    // your implementation
    }
}

该解决方案意味着更多的东西可能会实现 ComparableFoo - 情况可能并非如此,但是您正在对接口进行编码,并且泛型表达式很简单。

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.

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.

善良天后 2024-09-23 09:09:42

我知道你说你想要“compareTo(SubClass object),接受它自己类型的对象”,但我仍然建议像这样声明抽象类:

public abstract class MyClass implements Comparable <Object>

并在覆盖 MySubClass 中的compareTo时进行instanceof检查:

@Override
public int compareTo(Object o) {
    if (o instanceof MySubClass)) {
        ...
    }
    else throw new IllegalArgumentException(...)
}

类似于“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:

public abstract class MyClass implements Comparable <Object>

and do an instanceof check when overriding compareTo in MySubClass:

@Override
public int compareTo(Object o) {
    if (o instanceof MySubClass)) {
        ...
    }
    else throw new IllegalArgumentException(...)
}

similarly to 'equals' or 'clone'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文