Введите аргументы в объявлениях подкласса

В настоящее время я изучаю дженерики и с трудом понимаю некоторые их аспекты. Я чувствую, что что-то упустил, поэтому вопрос может показаться глупым.

Я понимаю, что есть:

  1. Заполнители, известные как "формальные параметры типа".
  2. Фактические "аргументы типа".

Вот пример кода, который у меня есть с обобщениями и цепочкой методов, которые работают:

class Clothing <T> {
    String material; 
    String color; 

    T setMaterial (String material) {
        this.material = material;
        return (T) this;
    }

    T setColor (String color) {
        this.color = color;
        return (T) this;
    }

}

class Jeans extends Clothing <Jeans>  {

}

class Pants extends Clothing <Pants>  {

}


class Executor {

    public static void main(String[] args){
        Jeans jeansPair = new Jeans().setMaterial("cotton").setColor("green");
    }

}

Проблема в том, что я не понимаю, почему arugment типа, такой как Jeans и Pants, предоставляется в объявлениях подкласса, а не в экземплярах, подобных тому, что в методе main.

Я был бы признателен, если бы вы предоставили ссылку на это правило - я искал много информации, такой как ограниченные параметры, необработанные типы, стирание и т. Д., Но не совсем нашел то, что искал.

Спасибо

1 ответ

Кроме того: вам, вероятно, будет проще с этими обобщениями, если вы будете использовать шаблон компоновщика, а не изменяемый шаблон, который вы здесь описываете. Я только что ответил на связанный вопрос, который дает пример такой структуры строителя.

Jeans а также Pants являются конкретными типами без универсального параметра, поэтому при их создании вы просто говорите new Jeans() / new Pants(); у них нет универсального типа, который может указать вызывающая сторона. Поскольку они также расширяют универсальный тип, вы можете сказать:

Clothing<Jeans> jeans = new Jeans()....;

если вы хотите сослаться на объект по его родителю общего типа. Это ничем не отличается от любых других отношений типа родитель / потомок, таких как List<String> против ArrayList<String>, Эти классы просто жестко кодируют значение универсального типа.

Вы можете представить себе копирование методов в Clothing в Jeans а также Pants и замена T с Jeans а также Pants соответственно, если это поможет вам понять, что делают эти классы.

Что касается того, почему аргумент типа предоставляется в объявлениях подкласса, это стилистический выбор, нет правила относительно того, когда его следует использовать. Хорошо, когда у вас есть конечное число типов, которые можно / нужно использовать в качестве универсального типа, так как теперь вызывающим объектам не нужно явно указывать тип каждый раз. Однако в "универсальном" случае, когда универсальный тип представляет произвольное число различных конкретных типов, этот шаблон вреден, поскольку автору класса необходимо определить новый подкласс для каждого данного типа.

Другие вопросы по тегам