Php ооп классы наследование

Наследование в объектно-ориентированном программировании PHP

Этот урок мы посвятим одной из ключевых тем объектно-ориентированного программирования – теме наследования. Благодаря реализации наследования мы можем организовать связь классов по принципу родительский-дочерний и добавлять дополнительную функциональность в разрабатываемые приложения без необходимости дублирования целых блоков кода.

Что такое наследование?

В объектно-ориентированном программировании наследование позволяет нам создать класс, который наследует функциональность и может использовать свойства и методы от другого класса. Это полезно, когда мы хотим создать класс, который расширяет функциональность исходного класса, не нарушая существующий код, который использует исходный класс.

Эту связь обычно описывают с помощью терминов «родительский» и «дочерний». Класс, от которого мы наследуем, называется базовым классом, суперклассом или родительским классом. Класс, который наследует функциональность, называется подклассом или дочерним классом. В наследовании у нас есть родительский класс со своими собственными методами и свойствами, а также дочерний класс (или классы), которые унаследуют все общедоступные и защищенные свойства и методы родительского класса. Кроме того, у них могут быть свои свойства и методы.

Используя наследование, мы можем создать повторно используемый фрагмент кода, который мы пишем только один раз в родительском классе и используем снова столько, сколько нам нужно в дочерних классах.

Как наследовать от другого класса?

Существующий класс готов к наследованию, нам не нужно делать с ним ничего особенного. Этот класс называется базовым классом, суперклассом или родительским классом.

Читайте также:  Php current working directory

В PHP мы используем ключевое слово extends , чтобы указать, что класс наследуется от другого класса.

Синтаксис

 class ChildClass extends ParentClass < >?>

В приведенном ниже примере класс SportsCar наследует класс Car , поэтому у него есть доступ ко всем методам и свойствам Car , которые не являются приватными. Это позволяет нам писать общедоступные методы setModel() и hello() только один раз в родительском классе, а затем использовать эти методы как в родительском, так и в дочернем классах:

Пример

 model = $model; > public function hello() < return "Бип! Я " . $this -> model . "
"; > > //Дочерний класс наследует код родительского класса class SportsCar extends Car < //Нет кода в дочернем классе >//Создаем экземпляр из дочернего класса $sportsCar1 = new SportsCar(); // Устанавливаем значение свойства класса // Для этого мы используем метод, который мы создали в родительском $sportsCar1 -> setModel('Mercedes Benz'); //Используем второй метод, который дочерний класс унаследовал от родительского класса echo $sportsCar1 -> hello(); ?>

Результат выполнения кода:

Собственные методы и свойства дочернего класса

Так же, как дочерний класс может использовать свойства и методы своего родительского класса, он также может иметь собственные свойства и методы. Однако, хотя дочерний класс может использовать код, унаследованный от родительского, родительскому классу не разрешается использовать код дочернего класса.

В приведенном ниже примере мы добавим в дочерний класс некоторый собственный код, добавив свойство $style , а также метод driveItWithStyle() :

Пример

 model = $model; > public function getModel() < return $this ->model; > > // Дочерний класс может использовать код, унаследованный от родительского класса, // а также может иметь собственный код class SportsCar extends Car < private $style = 'быстрый и надёжный'; public function driveItWithStyle() < return 'Автомобиль ' . $this ->getModel() . ' ' . $this -> style . ''; > > //создать экземпляр из дочернего класса $sportsCar1 = new SportsCar(); // Используем метод, который дочерний класс унаследовал от родительского класса $sportsCar1 -> setModel('Ferrari'); // Используем метод, который был добавлен в дочерний класс echo $sportsCar1 -> driveItWithStyle(); ?>

Результат выполнения кода:

Наследование и модификатор защищенного доступа

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

В этом уроке мы узнаем о третьем модификаторе — protected , который позволяет использовать код как внутри класса, так и из его дочерних классов.

Как вы думаете, что может случиться, когда мы попытаемся вызвать приватный метод или свойство извне класса?

Следующий пример демонстрирует, что может произойти, если мы объявляем свойство $model в родительском элементе приватным, но все же пытаемся получить к нему доступ из его дочернего класса:

Пример

 model = $model; > > // Дочерний класс class SportsCar extends Car < //Пытаемся получить доступ к приватному свойству model public function hello() < return "Бип! Я " . $this -> model . "
"; > > //Создаём экземпляр из дочернего класса $sportsCar1 = new SportsCar(); //Устанавливаем имя модели класса $sportsCar1 -> setModel('Mercedes Benz'); //Получаем значение свойства model echo $sportsCar1 -> hello(); ?>

Результат выполнения кода:

Мы не вывели значение модели автомобиля $model , потому что метод hello() в дочернем классе пытается получить доступ к приватному свойству $model , которое принадлежит родительскому классу.

Мы можем решить эту проблему, объявив свойство $model в родительском классе как защищенное protected , а не приватное, потому что, когда мы объявляем свойство или метод как защищенные, мы можем обращаться к нему как из родительского, так и из дочернего классов:

Пример

 model = $model; > > class SportsCar extends Car < // Теперь есть доступ к защищенному свойству, принадлежащему родителю public function hello() < return "Бип! Я " . $this -> model . "
"; > > //Создаём экземпляр из дочернего класса $sportsCar1 = new SportsCar(); //Задаём имя модели класса $sportsCar1 -> setModel('Mercedes Benz'); //Получаем имя модели класса echo $sportsCar1 -> hello(); ?>

Результат выполнения кода:

Сказанное выше относится и к методам:

Пример

name = $name; $this->color = $color; > protected function intro() < echo "Автомобиль name> имеет цвет: color>."; > > class SportsCar extends Car < public function message() < echo "Какой цвет у автомобиля? " . "
"; // доступ к защищенному методу, принадлежащему родителю $this -> intro(); > > //Создаём экземпляр из дочернего класса $sportsCar1 = new SportsCar('Mercedes Benz', 'Красный'); $sportsCar1 -> message(); ?>

Результат выполнения кода:

Публичный метод message() дочернего класса SportsCar имеет доступ к методу intro() (который защищен) родительского класса.

Переопределение родительских свойств и методов

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

Посмотрите на пример ниже. Методы __construct() и intro() в дочернем классе (SportsCar) переопределят методы __construct() и intro() в родительском классе (Car):

Пример

name = $name; $this->color = $color; > public function intro() < echo "Автомобиль name> имеет цвет: color>."; > > class SportsCar extends Car < public $weight; public function __construct($name, $color, $weight) < $this->name = $name; $this->color = $color; $this->weight = $weight; > public function intro() < echo "Автомобиль name> имеет цвет color>, а его вес weight> кг."; > > $sportsCar1 = new SportsCar('Mercedes Benz', 'Красный', 1800); $sportsCar1 -> intro(); ?>

Результат выполнения кода:

Ключевое слово final

Ключевое слово final может быть использовано для предотвращения наследования класса или для предотвращения переопределения метода.

В приведенном ниже примере мы объявляем класс Car как final, чтобы предотвратить наследование класса, но все же пытаемся его наследовать. В результате мы получим ошибку:

Пример

 // приведет к ошибке class SportsCar extends Car < // какой-то код >?>

Результат выполнения кода:

В следующем примере ключевое слово final испольуется для предотвращения переопределение метода:

Пример

 > class SportsCar extends Car < public function intro() < // приведет к ошибке // какой-то код >> ?>

Результат выполнения кода:

Попытка переопределить родительский метод intro(), защищенный ключевым словом final , привела к ошибке.

Заключение

Мы используем наследование, чтобы уменьшить дублирование кода за счет использования кода из родительского класса в дочерних классах. В этом уроке мы изучили один из принципов объектно-ориентированного программирования — концепцию наследования. Мы используем наследование, чтобы уменьшить дублирование кода, используя код родительского класса в дочерних классах. Щелкните здесь, чтобы попрактиковаться в предмете.

Источник

Наследование классов

Представьте, что у вас есть класс User . Он нужен вам для каких-то целей и в общем-то полностью вас устраивает — доработки этому классу в не нужны.

А теперь представим себе ситуацию, когда нам понадобился еще и класс Employee . Работник очень похож на юзера, имеет те же свойства и методы, но еще и добавляет свои — свойство salary , а также геттер и сеттер для этого свойства. Вот этот класс:

salary; > // Сеттер зарплаты public function setSalary($salary) < $this->salary = $salary; > public function getName() < return $this->age; > public function setName($name) < $this->name = $name; > public function getAge() < return $this->age; > public function setAge($age) < $this->age = $age; > > ?>

Как мы видим, код классов User и Employee практически полностью совпадает. Было бы намного лучше сделать так, чтобы общая часть была записана только в одном месте.

Для решения проблемы существует такая вещь, как . С помощью наследования мы можем заставить наш класс Employee позаимствовать () методы и свойства класса User и просто дополнить их своими методами и свойствами.

Класс, от которого наследуют называется ( англ. parent ), а класс, который наследует — . Класс-потомок наследует только публичные методы и свойства, но не приватные.

Наследование реализуется с помощью ключевого слова extends (переводится как расширяет ). Перепишем наш класс Employee так, чтобы он наследовал от User :

Проверим работу нового класса Employee :

setSalary(1000); // метод класса Employee $employee->setName(‘john’); // метод унаследован от родителя $employee->setAge(25); // метод унаследован от родителя echo $employee->getSalary(); // метод класса Employee echo $employee->getName(); // метод унаследован от родителя echo $employee->getAge(); // метод унаследован от родителя ?>

Класс-потомок не унаследовал от своего родителя приватные свойства name и age — попытка обратится к ним вызовет ошибку. При этом, однако, в классе-потомке доступны геттеры и сеттеры этих свойств, так как эти геттеры и сеттеры являются публичными.

Не подсматривая в мой код реализуйте такие же классы User , Employee .

Несколько потомков

Преимущества наследования в том, что каждый класс может несколько потомков. Давайте посмотрим на примере. Пусть кроме работника нам нужен еще и класс Student — давайте также унаследуем его от User :

Проверим работу нашего класса:

setCourse(3); // метод класса Student $student->setName(‘john’); // метод унаследован от родителя $student->setAge(25); // метод унаследован от родителя echo $student->getCourse(); // метод класса Student echo $student->getName(); // метод унаследован от родителя echo $student->getAge(); // метод унаследован от родителя ?>

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

Наследование от наследников

Пусть у нас есть класс-родитель и класс-потомок. От этого потомка также могут наследовать другие классы, от его потомков другие и так далее. Для примера пусть от класса User наследует Student , а от него в свою очередь наследует класс StudentBSU :

Сделайте класс Programmer , который будет наследовать от класса Employee . Пусть новый класс имеет свойство langs , в котором будет хранится массив языков, которыми владеет программист. Сделайте также геттер и сеттер для этого свойства.

Сделайте класс Driver ( водитель ), который будет наследовать от класса Employee . Пусть новый класс добавляет следующие свойства: водительский стаж, категория вождения (A, B, C, D), а также геттеры и сеттеры к ним.

Источник

Оцените статью