Зачем вообще нужно создавать конструктор, чтобы обратиться к полю?

Помогите понять.

Есть класс родителя, с полем:

public class Pet {    
    String name;    
}

Есть его наследник:

public class Cat extends Pet {
    private int age;
}

Почему, при создании объекта наследника я просто не могу указать поле родителя? Каким боком к полю наследника имеет отношение конструктор родителя?

То есть почему я просто не могу сделать так?

Конструктор наследника:

 public Cat(String name, int age) {
        super(name);
        this.age = age;
    }

Не создавая конструктор у родителя?

Ведь конструктор же, это по сути просто шаблон с какими полями нужно создать объект.


Ответы (3 шт):

Автор решения: Komdosh

В вашем примере всё довольно однозначно, но стоит его немного усложнить и становится непонятно что делать с данными:

public class Pet {    
    String name;    
    String alias;
}

Какой теперь конструктор должен быть? name первый аргумент конструктора, а alias второй?

Хорошо, но что если я ещё захочу дать значение по умолчанию:

public class Pet {    
    String name;    
    String alias = "actual pet";
}

Какой конструктор должен быть в этом случае? С двумя аргументами или одним? Или может там должен быть конструктор по умолчанию без аргументов? А что если я в конструкторе ещё хочу произвести трансформацию этой строки, чтобы она удовлетворяла системе (например добавить префикс).

Код должен однозначно описывать желаемое вами поведение, компьютеры, к сожалению, ещё не могут додумать за нас, чего мы хотим.

→ Ссылка
Автор решения: Roman C

Ваше утверждение неверно:

Ведь конструктор же, это по сути просто шаблон с какими полями нужно создать объект.

Конструктор вызывается при создании объекта, причем параметры конструктора не определяют с какими полями этот объект создается, а позволяют передать значения переменных в конструктор при его вызове. Эти значения выбираются произвольно, и независимо от полей класса наследника или его родителя. Просто если класс имеет поля, то в конструктор можно передать значения параметров, для того, чтобы инициализировать поля, или для других целей. Названия и количество параметров конструктора необязательно должны соответствовать полям. Если есть параметры, которые имеют названия такие же как названия полей, то для доступа к полям можно использовать ключевое слово this.

Почему, при создании объекта наследника я просто не могу указать поле родителя?

При создании объекта наследника создаются все поля, включая родителя. Они создаются инлайн до вызовов конструкторов. Конструктора вызываются в определенном порядке, о котором можно почитать здесь.

Опять же, если вы думали, что можете указать поле родителя как параметр конструктора, то это неверно. Вам нужно понять, что создание объекта - это сложная процедура, которая производится в определенном порядке, и вызов конструкторов имеет свое место и время.

Каким боком к полю наследника имеет отношение конструктор родителя?

Наверно вы думали, что с помощью конструктора наследника можно инициализировать поля родителя без вызова конструктора родителя. Это неверно. Для инициализации полей родителя можно вызвать конструктор родителя и передать значение поля с помощью super(). Я уже описал выше зачем нужно вызывать конструктор родителя, а к полю наследника действительно никакого отношения не имеет.

→ Ссылка
Автор решения: Vadik

Так как у вас поле name у класса Pet не приватное, то без создания родительского конструктора можно сделать так:

public Cat(String name, int age) {
    this.name = name;
    this.age = age;
}

Если класс Pet у вас лежит в другом пакете, тогда поле name нужно сделать protected:

public class Pet {
    protected String name;
}
→ Ссылка