-2

I was wondering why we have to use extends in java generics. For example:

class Team<T extends Player>

And we could have different types of players that inherit from the original Player class:

class FootballPlayer extends Player

class BaseballPlayer extends Player

Why do we have to use <T extends Player> in the Team class. Can't we just use Player?

When we add for example FootballPlayer to <extends Player> it works fine, but surely if we added FootballPlayer to <Player>, then it would work, because FootballPlayer is a player? When we do <T extends Player>, that means that anything we add must inherit from Player. So why doesn't simply <Player> work?

Thanks

  • 1
    For what part would you just want to use `Player`? Instead of the `T`? Then, no. Because the `T` is a _type variable_ whereas `Player` is a _type_. – Seelenvirtuose Jun 18 '20 at 17:42
  • 3
    Does this answer your question? [Is List a subclass of List? Why are Java generics not implicitly polymorphic?](https://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-are-java-generics-not-implicitly-po) – PiRocks Jun 18 '20 at 17:43
  • @PiRocks it sort of does. But why do we have to use extends instead of Player? When we add for example `FootballPlayer` to `` it works fine, but surely if we added `FootballPlayer` to ``, then it would work, because `FootballPlayer` is a player? When we do `` work? Thanks – I_keep_getting_downvoted Jun 18 '20 at 17:54
  • @Seelenvirtuose so are you saying if we were to just use ``, then we couldn't add subclasses of `Player`, but if we do `` then we could? Thanks – I_keep_getting_downvoted Jun 18 '20 at 17:57
  • 2
    You can have a class `Team`, but it does not do what you think it does. In that case the `Player` is only a type variable! It is equivalent to `Team`! – Seelenvirtuose Jun 18 '20 at 18:03

1 Answers1

1

We have to use T extends Player as using just Player would defeat the purpose of using generics. If we didn't care about the specific type of player then we could simply use Player within the class wherever you would use T. The purpose of generics is to further narrow the types which are accepted based on the types within the angle brackets, <>.

For example

public class Player {
    public void celebrate() {
        System.out.println("yay!");
    }
}

public class Team<T extends Player> {
    private T[] players;

    public void setPlayers(T[] players) {
        this.players = players;
    }

    public void won() {
        for (T player : players) {
            // as T is a subclass of player we know it can celebrate
            player.celebrate();
        }
    }

    public static void main(String[] args) {
        Team<BaseballPlayer> baseballPlayerTeam = new Team<>();
        // this is fine as baseballPlayerTeam has class BaseballPlayer as a parameter.
        baseballPlayerTeam.setPlayers(new BaseballPlayer[] {new BaseballPlayer()});
        // this is not as a member of the Player[] can be an object which is not of type BaseballPlayer.
        baseballPlayerTeam.setPlayers(new Player[] {new FootballPlayer()});
    }
}

By saying we enforce that T must be a subclass of Player and therefore must have all the attributes and methods that Player has. Therefore within the class we can use use these without getting compile-time errors.

There isn't anything stopping you using Player as a type parameter, in which case you can use any type of player, but you won't get the advantage of any checks!

Alan
  • 48
  • 4