【问题标题】:Java problem inheriting interface implementation when extending a class扩展类时继承接口实现的Java问题
【发布时间】:2022-01-25 08:36:56
【问题描述】:

我正在努力让接口实现在另一个类中被继承:

我有一个需要实现 compareTo 的通用类。该类称为 GenericList 并实现为:

public class GenericList<T extends Comparable<T>> {
    private T[] items;
    private int count;
    public GenericList() {
        items = (T[]) new Comparable[10];
        count = 0;
    }
}

我有一个实现 compareTo 的 User 类:

public class User implements Comparable<User> {
    private String email;

    public User(String email) {
        this.email = email;
    }

    @Override
    public int compareTo(User o) {
        return (email.compareTo(o.email));

    }
}

创建用户的通用列表没有问题:

var users = new GenericList<User>();

如果我创建一个扩展 User 的类并尝试创建该类型的通用列表,则会收到错误消息。我创建了一个名为 Instructor 的类:

public class Instructor extends User{
    public Instructor(String email){
        super(email);
    }
}

如果我使用该类创建一个通用列表:

var instructors = new GenericList<Instructor>();

我收到一个错误:

Type parameter 'com.martin.Instructor' is not within its bound; should implement 'java.lang.Comparable<com.martin.Instructor>'

不应该使用继承的 compareTo 方法吗?

我尝试了很多不同的方法,但我无法让 GenericList 使用这样的继承类。

谢谢

【问题讨论】:

  • 讲师继承compareTo(User)。接口需要compareTo(Instructor)
  • 澄清一下,Instructor 需要实现 int compareTo(Instructor),即使它只是委托给它的超类。
  • 你可以尝试声明public class GenericList&lt;T extends Comparable&lt;? super T&gt;&gt; { private T[] items;
  • 另外,在 GenericList 构造函数中的强制类型现在可以擦除类型,但如果我们得到具体化的泛型,就会中断。
  • Martin... 从逻辑上考虑前两个 cmets。 Instructor 可以有其他字段,当您仅比较通用 User 时,这些字段不会被考虑在内。这就是为什么Instructor 必须有一个compareTo() 方法。

标签: java


【解决方案1】:

public class GenericList&lt;T extends Comparable&lt;T&gt;&gt;

当您声明GenericList&lt;Instructor&gt; 时,上述声明将T 替换为Instructor。所以现在它说Instructor 必须扩展(或实现,真的)Comparable&lt;Instructor&gt;。问题是Instructor 扩展了User,它实现了Comparable&lt;User&gt;,但没有实现Comparable&lt;Instructor&gt;

所以问题在试图找到继承的compareTo() 方法之前就已经解决了。修复即时编译器错误的一种方法是更改​​ GenericList 声明:

public class GenericList<T extends Comparable<? super T>>

这使用Comparable 接口上的类型捕获。

现在公平警告,我已检查此更改是否会编译 here,但除此之外我还没有测试它,因为您的问题在创建后没有提供 GenericList 的任何用法。

【讨论】:

  • 非常感谢您的所有建议 - 辛苦了!
【解决方案2】:

整体逻辑似乎是正确的:User 和 Comperable 是 Instructor 类的超类型,即 Instructor 的实例可以同时表示它们。但这里有一个问题:

var ints1 = (Comparable<Instructor>) new Instructor("name"); // this line will not compline
var ints2 = (Comparable<User>) new Instructor("name"); // no errors here

第一行会导致编译错误,因为Instructor类的继承链中没有Comparable的实现,但是有Comparable的实现 这是类 User 本身。因此 Instructor 类继承的 compareTo() 方法的签名将是 compareTo(User user)。

快速提醒:泛型是不变的,即对于 List 类型的变量,我们只能分配 List,而不是 List 或 List。类似的类型 ComparableComparable 不能相互比较,尽管 User 是 Instructor 的超类型。这就是所谓的不变性,它的主要目的是强制类型安全。

出于良心,不可能将 Instructor 对象强制为 Comparable 类型。

一种可能的补救方法是在 Instructor 类中实现 Comparable,只有当 Instructor 定义了一些自己的属性来建立其实例的唯一性时,它才会有用,或者change the declaration of generic type as already shown here

【讨论】:

    猜你喜欢
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 2015-08-03
    • 2021-06-24
    • 1970-01-01
    • 2012-10-25
    相关资源
    最近更新 更多