不能使用与父子孙子相媲美的继承

2022-09-04 01:11:45

给定以下代码:

public abstract class Participant {
    private String fullName;

    public Participant(String newFullName) {
        this.fullName = new String(newFullName);
    }

    // some more code 
}


public class Player extends Participant implements Comparable <Player> {    
    private int scoredGoals;

    public Player(String newFullName, int scored) {
        super(newFullName);
        this.scoredGoals = scored;
    }

    public int compareTo (Player otherPlayer) {
        Integer _scoredGoals = new Integer(this.scoredGoals);
        return _scoredGoals.compareTo(otherPlayer.getPlayerGoals());
    }

    // more irrelevant code 
}

public class Goalkeeper extends Player implements Comparable <Goalkeeper> { 
    private int missedGoals;        

    public Goalkeeper(String newFullName) {
        super(newFullName,0);
        missedGoals = 0;
    }

    public int compareTo (Goalkeeper otherGoalkeeper) {
        Integer _missedGoals = new Integer(this.missedGoals);
        return _missedGoals.compareTo(otherGoalkeeper.getMissedGoals());
    }

    // more code 
}

问题是这不会遵守。Goalkeeper

当我尝试编译该代码时,Eclipse 会抛出:

The interface Comparable cannot be implemented more than once with 
different arguments: Comparable<Player> and Comparable<Goalkeeper>

我不是想与 进行比较,而是与 ,并且只与他进行比较。PlayerGoalkeeper

我做错了什么?


答案 1

Angelika Langer的Generics FAQ #401中描述了这个问题:

一个类能否实现同一泛型接口的不同实例化?

不可以,类型不得直接或间接派生自同一泛型接口的两个不同实例化。

此限制的原因是按类型擦除进行转换。类型擦除后,同一泛型接口的不同实例化将折叠为同一原始类型。在运行时,不同实例化之间不再有区别。

(我强烈建议查看问题的整个描述:它比我引用的内容更有趣。

要变通解决此问题,您可以尝试以下操作:

public class Player<E extends Player> extends Participant implements Comparable<E> {
    // ...
    public int compareTo(E otherPlayer) {
        Integer _scoredGoals = this.scoredGoals;
        return _scoredGoals.compareTo(otherPlayer.getPlayerGoals());
    }
    // ...
}


public class Goalkeeper extends Player<Goalkeeper> {
    // ...
    @Override
    public int compareTo(Goalkeeper otherGoalkeeper) {
        Integer _missedGoals = this.missedGoals;
        return _missedGoals.compareTo(otherGoalkeeper.getMissedGoals());
    }
    // ...
}

答案 2

就你的设计的逻辑而言,你没有做错任何事。但是,Java 有一个限制,它阻止您实现具有不同类型参数的相同泛型接口,这是由于它实现泛型的方式(通过类型擦除)。

在你的代码中,继承自 它的实现,并尝试添加自己的;这是不允许的。GoalkeeperPlayerComparable <Player>Comparable <Goalkeeper>

解决这个限制的最简单方法是覆盖 ,将球员传入,并将其与守门员进行比较。Comparable <Player>GoalkeeperGoalkeeperthis

编辑

public int compareTo (Player otherPlayer) {
    Goalkeeper otherGoalkeeper = (Goalkeeper)otherPlayer;
    Integer _missedGoals = new Integer(this.missedGoals);
    return _missedGoals.compareTo(otherGoalkeeper.getMissedGoals());
}

推荐