Java继承类时实现接口的问题

3

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

我有一个需要实现compareTo方法的通用类,它称为GenericList并且实现如下:

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

我有一个User类,实现了compareTo方法:

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 使用像这样的继承类。

谢谢


3
教练类继承了 compareTo(User) 方法。接口要求实现 compareTo(Instructor) 方法。 - Andy Thomas
3
需要澄清的是,即使Instructor只是委托给其超类,它也需要实现 int compareTo(Instructor) - Jim Garrison
1
你可以尝试声明 public class GenericList<T extends Comparable<? super T>> { private T[] items; - Iłya Bursov
1
此外,GenericList构造函数中的强制类型转换现在可以通过类型擦除来实现,但如果我们将来使用具体化的泛型,则会出现问题。 - Andy Thomas
1
马丁,请理性思考前两条评论。当你仅比较通用的“用户”时,教练可以有额外的字段未被考虑到。这就是为什么“教练”必须有一个“compareTo()”方法的原因。 - hfontanez
1
感谢大家的建议。我已经使用public class GenericList<T extends Comparable<? super T>>使其正常工作。 - Martin Williams
2个回答

4

public class GenericList<T extends Comparable<T>>

如果你声明了GenericList<Instructor>,那么上面的声明将用Instructor替换T。因此现在它表示Instructor必须扩展(或实现)Comparable<Instructor>。问题在于,Instructor扩展了User,而User实现了Comparable<User>,但没有实现Comparable<Instructor>

因此,在尝试查找继承的compareTo()方法之前,就已经存在问题。解决即时编译器错误的一种方法是更改GenericList声明:

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

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

请注意,我已经检查过这个更改将在这里编译,但因为您的问题没有提供创建后对 GenericList 的任何用法,所以我没有进行其他测试。


非常感谢您提供的所有建议 - 真是太有效了! - Martin Williams

1
整体逻辑似乎是正确的:用户和可比较类型是 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。同样,类型 Comparable 和 Comparable 不能相互比较,无论 User 是否是 Instructor 的超类型。这就是所谓的不变性,其主要目的是强制执行类型安全。
作为这一点的良心,不可能将 Instructor 对象强制转换为 Comparable 类型。
一个可能的解决方法是在 Instructor 类中实现 Comparable,仅当 Instructor 定义了一些自己的属性来建立其实例的唯一性时,它才有用,或者更改通用类型的声明,如已在此处显示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接