2012-01-01 4 views
7

Biorąc pod uwagę następujący kod:Nie można użyć porównywalny ze ojciec-syn-wnukiem dziedziczenia

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 
} 

Problemem jest to, że nie będzie complie Goalkeeper.

Kiedy próbuję skompilować ten kod Eclipse rzuca:

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

ja nie staram się porównać z Player, ale z Goalkeeper i tylko z nim.

Co robię źle?

+0

proszę można naprawić wcięcia i odstępy W przykładzie kodu. To bardzo trudne do odczytania. –

+0

Zrobione, przepraszam! Mam nadzieję, że teraz jest w porządku. – ron

+0

Dlaczego 'nowy ciąg()' w konstruktorów? Ciągi są niezmienne! – fge

Odpowiedz

4

Jeśli chodzi o logikę projektu, nie robisz nic złego. Jednak Java ma ograniczenia, które uniemożliwiają zastosowanie tego samego interfejsu generycznego z różnymi parametrami typu, co wynika ze sposobu implementacji generycznych (poprzez usuwanie typu).

W kodzie Goalkeeper dziedziczy z Player jego realizacja Comparable <Player> i próbuje dodać Comparable <Goalkeeper> z własnej; to nie jest dozwolone.

Najprostszym sposobem rozwiązania tego ograniczenia jest przesłonić Comparable <Player> w Goalkeeper, oddanych odtwarzacz przeszedł do Goalkeeper i porównać go do this bramkarza.

Edit

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

To znaczy, aby to zrobić: "public class Bramkarz rozciąga Gracz realizuje Porównywalne " ... \t public int compareTo (Bramkarz otherGoalkeeper) \t { \t \t Integer _missedGoals = new Integer (this.missedGoals); \t return _missedGoals.compareTo (otherGoalkeeper.getMissedGoals()); \t} "?? – ron

+2

@ron Nie musisz nawet robić" implementuje Porównywalne ": jest tam, ponieważ rozszerzasz' Player'. Po prostu wykonaj to: '@Override public int compareTo (Player otherGoalkeeper) {...} ' – dasblinkenlight

+0

to jest problem: Proszę zauważyć, że klasa Player nie mają missedGoals dziedzinie, a klasa Goalkepper nie zrobiłem tego. public int compareTo (Bramkarz otherGoalkeeper) \t { \t \t Integer _missedGoals = new Integer (this.missedGoals); \t \t return _missedGoals.compareTo (otherGoalkeeper.getMissedGoals()); \t} – ron

11

Problem jest opisany w Angelika Langera Generics FAQ #401:

Can klasy implementują różne dawałaby tego samego generycznego interfejsu?

Nie, typ nie może bezpośrednio lub pośrednio pochodzić z dwóch różnych wystąpień tego samego interfejsu ogólnego.

Powodem dla tego ograniczenia jest tłumaczenie według typu. Po typie wymaż różne instancje tego samego interfejsu ogólnego, zwinięte w ten sam surowy typ. W czasie wykonywania nie ma już żadnego rozróżnienia między różnymi instancjami.

(Gorąco polecam sprawdzić cały opis problemu. Jest to bardziej interesujące niż to, co już notowane)

W celu obejścia tego ograniczenia, można spróbować wykonać następujące czynności:

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()); 
    } 
    // ... 
} 
+0

+1 za wzmiankę o dokładnym źródle na ten temat od Angeliki Langer. – Kjellski

Powiązane problemy