При работе с классами в PHP часто приходится расширять функционал кода. Но если изменять оригинальный класс нет возможности, то его можно легко расширить создав "копию".
Классы, которые расширяют оригинальный называют "дочерними", а родительский - "суперклассом". У суперкласса может быть множество дочерних классов.
extends
Рассмотрим основные принципы наследования классов:
- С помощью наследования мы можем создавать классы, которые будут содержать в себе все свойства и методы родительского класса, т.е. дочерние классы наследуют public и protected свойства и методы родительского класса.
- Дочерний класс является расширением родительского класса, так как кроме унаследованных свойств и методов он может содержать собственные.
- Наследование устанавливается использованием слова extends при создании класса.
- Если у наследника нет своего конструктора (о нем писал ранее), то автоматически запустится конструктор родителя. Если в дочернем классе есть конструктор, то родительский конструктор не будет запускаться.
- В дочерних классах могут переопределяться свойства и методы суперкласса. Определяя подкласс, мы гарантируем, что его экземпляр определяется характеристиками сначала дочернего, а затем родительского класса.
Давайте рассмотрим простой пример. Пусть у нас есть класс Ploshad, который считает площадь поверхности. Но теперь нам понадобилось рассчитывать ее объем. Оригинальный класс изменять нельзя. Создадим дочерний класс Obyem, который будет наследовать все свойства и методы Ploshad, и добавим функционал для расчета объема:
class Ploshad {
protected $width;
protected $height;
public function __construct($x, $y) {
$this->width = $x;
$this->height = $y; }
public function Square() { return $this->width * $this->height; }
}
class Obyem extends Ploshad {
protected $glybina;
public function Obyemss($g) {
$this->glybina = $g;
return $this->Square()* $this->glybina;
}
}
За счет записи class Obyem extends Ploshad мы объявили, что класс Obyem наследует свойства и методы класса Ploshad и может ими управлять. Внутри Obyem мы прописали новой свойство $glybina и метод public function Obyemss($g). Давайте теперь рассчитаем объем и площадь:
$obj = new Obyem(2,12); //создаем объект от наследника
echo 'Площадь: '.$obj->Square(); //старая функция родителяя
echo 'Объем: '.$obj->Obyemss(2); //новая функция наследника
Как видно из комментариев $obj теперь может использовать как старые методы класса Ploshad, так и новые дочернего класса Obyem.
При рассчете площади интерпретатор PHP ищет конструктор в Obyem классе, если его не находи, то запускает конструктор в Ploshad. Он переопределяет значения переданных свойств( Obyem(2,12) ). Затем запускается метод Square() и использует эти данные.
В случае с объемом, также запускается конструктор в Ploshad, а затем метод Obyemss($g), в которой передается высота. Внутри метода используем рассчет площади умноженный на высоту и получаем результат.
Наследование используют, когда функционал внутри одного класса становится слишком сложным для понимания и работы с ним, а также для создания исключений или разграничения типов данных. Например, у вас есть класс для выгрузки книжных товаров с множеством полей (автор, год издания, число страниц). Теперь, если вам понадобилось выводить товар с другим типом, например: DVD игры, то у него будут другие параметры (системные требования). Поэтому если класс стал напоминать два класса, лучше сделать наследование.
Интерпретатор PHP всегда сначала смотрит на дочерний класс:
- Есть ли конструктор. Если есть, то игнорирует конструктор родителя
- Есть ли свойства и методы. Если в дочернем и родительском они совпадают, то используются дочерние. Таким образом, можно полностью переписать функционал методов родительского класса.
extends parent::
parent:: - используется если в дочернем классе нужно изменить функционал родительского метода
Пример:
class PloshadProcent extends Ploshad {
function Square() {
$str = parent::Square();
$str = $str*0.1;
return $str;
}
}
Теперь при вызове, мы получим 10% от нашей площади:
$obj2 = new PloshadProcent(2,12);
echo 'Площадь 10%: '.$obj2->Square(); //выдаст 2.4
Мы переопредилили метод суперкласса Square() внутри PloshadProcent
Второй и очень важный способ применения parent:: заключается в переопределении функционала конструктора внутри дочернего класса. Это можно использовать, если в суперклассе нет каких-то новых свойств, для работы:
Пусть есть класс book и в нем конструктор принимает всего 2 параметра: $title, $price.
class book {
public $title;
public $price;
function __construct($title, $price) {
$this->title = $title;
$this->price = $price;
}
}
Вдруг нам понадобилось вывести новый параметр $pages. Создадим экземпляр класса new_book и сделаем в нем свой конструктор, в котором уже будут нужные данные: $title, $price, $pages
Когда в дочернем классе определяется свой конструктор, PHP не вызывает конструктор родительского класса автоматически. Это необходимо сделать вручную в конструкторе подкласса.
Дочерний класс в своем конструкторе вызывает конструктор своего родительского класса, передавая нужные аргументы для инициализации, исполняет его, а затем выполняется код, который реализует дополнительную функциональность, в данном случае инициализирует свойство подкласса.
class new_book extends book {
public $pages;
function __construct($title, $price, $pages) {
parent::__construct($title, $price); // вызываем метод-конструктор родительского класса
$this->pages = $pages; // инициализируем свойство определенное в подклассе
}
}
$obj = new new_book('азбука', 35, 500);
echo "Книга: $obj->title | Цена: $obj->price | Страниц: $obj->pages";
Таким образом, мы можем расширять функционал суперклассов, не изменяя их самих. В следующем уроке вы узнаете о статических свойствах и методах.
Добавить комментарий