# Перезапись конструктора родителя в потомке

Пусть у нас есть вот такой класс `User`, у которого свойства `name` и `age` задаются в конструкторе и в дальнейшем доступны только для чтения (то есть приватные и имеют только геттеры, но не сеттеры):

`<?php class User { private $name; private $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>`

От этого класса наследует класс `Student`:

`<?php class Student extends User { private $course; public function getCourse() { return $this->course; } } ?>`

Класс-потомок не имеет своего конструктора - это значит что при создании объекта класса сработает конструктор родителя:

`<?php $student = new Student('john', 19); // сработает конструктор родителя echo $student->getName(); // выведет 'john' echo $student->getAge(); // выведет 19 ?>`

Все замечательно, но есть проблема: мы бы хотели при создании объекта класса `Student` третьим параметром передавать еще и курс, вот так:

`<?php $student = new Student('john', 19, 2); // это пока не работает ?>`

Самое простое, что можно сделать, это переопределить конструктор родителя своим конструктором, забрав из родителя его код:

`<?php class Student extends User { private $course; // Конструктор объекта: public function __construct($name, $age, $course) { // Дублируем код конструктора родителя: $this->name = $name; $this->age = $age; // Наш код: $this->course = $course; } public function getCourse() { return $this->course; } } ?>`

При этом мы в классе потомке обращаемся к приватным свойствам родителя `name` и `age`, что, конечно же, не будет работать так, как нам нужно. Переделаем их на `protected`:

`<?php class User { protected $name; // объявим свойство защищенным protected $age; // объявим свойство защищенным // Конструктор объекта: public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>`

Теперь при создании студента третьим параметром мы можем передать и курс:

`<?php $student = new Student('john', 19, 2); // теперь это работает echo $student->getName(); // выведет 'john' echo $student->getAge(); // выведет 19 echo $student->getCourse(); // выведет 2 ?>`

Не подсматривая в мой код реализуйте такой же класс `Student`, наследующий от `User`.

## Используем конструктор родителя

Понятно, что дублирование кода родителя в классе потомке - это не очень хорошо. Давайте вместо дублирования кода в конструкторе потомка вызовем конструктор родителя.

Для полной ясности распишу все по шагам. Вот так выглядит конструктор класса `User`, он принимает два параметра `$name` и `$age` и записывает их в соответствующие свойства:

`<?php // Конструктор объекта класса User: public function __construct($name, $age) { $this->name = $name; $this->age = $age; } ?>`

Вот конструктор класса `Student`, который мы хотим переписать:

`<?php // Конструктор объекта класса Student: public function __construct($name, $age, $course) { // Этот код хотим заменить на вызов конструктора родителя: $this->name = $name; $this->age = $age; // Наш код: $this->course = $course; } ?>`

Конструктор родителя можно вызвать внутри потомка с помощью `parent`. При этом конструктор родителя первым параметром ожидает имя, а вторым - возраст, и мы должны ему их передать, вот так:

`<?php // Конструктор объекта класса Student: public function __construct($name, $age, $course) { // Вызовем конструктор родителя, передав ему два параметра: parent::__construct($name, $age); // Запишем свойство course: $this->course = $course; } ?>`

Напишем полный код класса `Student`:

`<?php class Student extends User { private $course; // Конструктор объекта: public function __construct($name, $age, $course) { parent::__construct($name, $age); // вызываем конструктор родителя $this->course = $course; } public function getCourse() { return $this->course; } } ?>`

Проверим, что все работает:

`<?php $student = new Student('john', 19, 2); echo $student->getName(); // выведет 'john' echo $student->getAge(); // выведет 19 echo $student->getCourse(); // выведет 2 ?>`

Так как класс `Student` теперь не обращается напрямую к свойствам `name` и `age` родителя, можно их опять сделать приватными:

`<?php class User { private $name; // объявим свойство приватным private $age; // объявим свойство приватным public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function getName() { return $this->name; } public function getAge() { return $this->age; } } ?>`

Сделайте класс `User`, в котором будут следующие свойства только для чтения: `name` и `surname`. Начальные значения этих свойств должны устанавливаться в конструкторе. Сделайте также геттеры этих свойств.

Модифицируйте предыдущую задачу так, чтобы третьим параметром в конструктор передавалась дата рождения работника в формате год-месяц-день. Запишите ее в свойство `birthday`. Сделайте геттер для этого свойства.

Модифицируйте предыдущую задачу так, чтобы был приватный метод `calculateAge`, который параметром будет принимать дату рождения, а возвращать возраст с учетом того, был ли уже день рождения в этом году, или нет.

Модифицируйте предыдущую задачу так, чтобы метод `calculateAge` вызывался в конструкторе объекта, рассчитывал возраст пользователя и записывал его в приватное свойство `age`. Сделайте геттер для этого свойства.

Сделайте класс `Employee`, который будет наследовать от класса `User`. Пусть новый класс имеет свойство `salary`, в котором будет хранится зарплата работника. Зарплата должна передаваться четвертым параметром в конструктор объекта. Сделайте также геттер для этого свойства.

←→
↑