Зачем нам нужно расширяться при использовании дженериков в Java, если мы можем просто использовать исходный тип? - PullRequest
0 голосов
/ 18 июня 2020

Мне было интересно, почему мы должны использовать extends в java дженериках. Например:

class Team<T extends Player>

И у нас могут быть разные типы игроков, унаследованные от исходного класса Player:

class FootballPlayer extends Player

class BaseballPlayer extends Player

Почему мы должны использовать <T extends Player> в Team класс. Разве мы не можем просто использовать Player?

Когда мы добавляем, например, FootballPlayer к <extends Player>, это работает нормально, но, конечно, если бы мы добавили FootballPlayer к <Player>, тогда это сработало бы, потому что FootballPlayer - это игрок? Когда мы делаем <T extends Player>, это означает, что все, что мы добавляем, должно наследовать от Player. Так почему же просто <Player> не работает?

Спасибо

1 Ответ

1 голос
/ 18 июня 2020

Мы должны использовать T extends Player, так как использование только Player лишит смысла использование универсальных типов. Если бы нас не заботил конкретный c тип игрока, мы могли бы просто использовать Player в классе везде, где вы бы использовали T. Цель универсальных типов - еще больше сузить типы, которые принимаются на основе типов в пределах угла скобки, <>.

Например,

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()});
    }
}

Говоря, мы устанавливаем, что T должен быть подклассом Player и, следовательно, должен иметь все атрибуты и методы, которые есть у Player. Следовательно, внутри класса мы можем использовать их, не получая ошибок времени компиляции.

Ничто не мешает вам использовать Player в качестве параметра типа, и в этом случае вы можете использовать любой тип игрока, но вы не получите преимущества каких-либо проверок!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...