简体   繁体   中英

Inherit extended generic type from an interface

I'm worried I've phrased this question wrongly, so here is an example to illustrate:

I have an interface:

public interface ICard  extends Comparable<T>{

    public abstract String toString();

    public abstract int compareTo(T o) throws WrongCardTypeException;

}

What I want is that the class implementing ICard automagically implements Comparable<T> so that you can only compare whatever class implements ICard

Instead I need to specify the generic for the comparable extension and use the sort of instancof check below

public interface ICard  extends Comparable<ICard>{

    public abstract String toString();

    public abstract int compareTo(ICard o) throws WrongCardTypeException;

}

public class PlayingCard implements ICard{
    public enum Rank { TWO, THREE, FOUR, FIVE, SIX,
        SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }

    public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }

    private  Rank rank;
    private  Suit suit;

    public PlayingCard(Rank rank, Suit suit) {
        this.rank = rank;
        this.suit = suit;
    }

    public Rank getRank() { return rank; }

    public Suit getSuit() { return suit; }


    @Override
    public String toString() { return rank + " of " + suit; }

    @Override
    public int compareTo(ICard o) throws WrongCardTypeException {
        if (o instanceof PlayingCard){
        PlayingCard c = (PlayingCard)o;
        int rankCompare = rank.compareTo(c.rank);
        return rankCompare != 0 ? rankCompare : suit.compareTo(c.suit);
        }
    throw new WrongCardTypeException("Tried to compare "+o.getClass().getCanonicalName()+" to "+ this.getClass().getCanonicalName());
    }

I was wondering if there was a neater way to do this that would let me do away with the the instanceof check? Wildcards? I'm not sure here. Or is the instanceof check ok? I've heard it has 'code smell', eg was bad practice.


I have a similar (?) issue with my IDeck interface:

public interface IDeck<T extends ICard> extends Comparable<T>, Collection<T>{
    public ArrayList<T> getDeck();
    public void setDeck(Set<T> newDeck);
}

In the class that implements this, my compareTo method takes parameters of type ICard , though I want to compare decks that inherit from IDeck.

You can make your ICard interface generic, with a bound, so it any generic type parameter must itself be an ICard .

public interface ICard<T extends ICard<T>>  extends Comparable<T>{

Then you can specify PlayingCard in the ICard interface in the PlayingCard class:

public class PlayingCard implements ICard<PlayingCard> {

I think you want

public interface ICard<T> extends Comparable<T>{

  public abstract String toString();

  public abstract int compareTo(T o) throws WrongCardTypeException;

}

(note the ICard<T> )

and then PlayingCard implements ICard<PlayingCard> .

That said, this interface gets you exactly nothing over the Comparable interface, since toString() is already available for all Java objects, and trying to require it will have no effect.

您需要“重新指定” T,尝试:

public interface ICard<T> extends Comparable<T>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM