Невозможно использовать сравнимое с наследием отец-сын-внук - PullRequest
10 голосов
/ 01 января 2012

С учетом следующего кода:

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>

Я не пытаюсь сравнивать с Player, а с Goalkeeper и только с ним.

Что я делаю не так?

Ответы [ 2 ]

13 голосов
/ 01 января 2012

Проблема описана в Общих вопросах Анжелики Лангер # 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());
    }
    // ...
}
4 голосов
/ 01 января 2012

Что касается логики вашего дизайна, вы не делаете ничего плохого. Однако в Java есть ограничение, которое не позволяет вам реализовать один и тот же универсальный интерфейс с различными параметрами типа, что связано с тем, как он реализует универсальные интерфейсы (посредством стирания типов).

В вашем коде Goalkeeper наследует от Player свою реализацию Comparable <Player> и пытается добавить собственную Comparable <Goalkeeper>; это не разрешено.

Простейший способ преодолеть это ограничение - переопределить Comparable <Player> в Goalkeeper, привести игрока к Goalkeeper и сравнить его с this вратарем.

Редактировать

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