Наследование в ООП PHP. Ключевое слово parent

Наследование
Ключевое слово parent



Наследование: php.net

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



Наследование - это некий механизм, посредством которого один или несколько классов можно получить из некоторого базового класса.


Класс Product (базовый класс) - должен содержать общие свойста и общие методы (общую логику).

Поэтому удаляем из класса все частные свойства и методы. - Оставляем свойства общие для всех товаров.
- Конструктр будет задавать свойства, общие для всех товаров.
- Получим через гетеры getName() и getPrice() общие свойства товаров.
- Метод getProduct() - будет возвращать инфрмацию о товаре, используя общие свойства.


Файл Product.php


-- файл Product.php --

<?php
class Product
{
// общие свойства товаров
public $name; // наименование товара
public $price ; // цена товара

// конструктр будет задавать свойства, общие для всех
public function __construct($name, $price)
{
$this -> name = $name;
$this -> price = $price;
}

// метод getProduct() - будет возвращать инфрмацию о товаре, используя общие свойства
public function getProduct($type = 'notebook')
{
$out = "<hr><b>О товаре:<b><br>
Наименование: {$this->name}<br>
Цена: {$this->price}<br> ";
}

// общие гетеры:
public function getName()
{
return $this -> name ;
}

public function getPrice()
{
return $this -> price ;
}
}
?>





В индексом файле в экземпляры класса передаем по два параметра: название и цена. Получаем общую для всех типов товаров информацию с помощью метода getProduct().


Файл index.php


-- файл index.php --

<?php
error_reporting(-1);
require_once 'classes/Product.php';
function debug($data)
{
echo '<pre>' . print_r($data, 1 ) . '</pre>';
}

// В экземпляре класса Product (книжка) - передаем только два параметра
$book = new Product('Три мушкетера', 20);

// экземпляр класса Product (ноутбук)
$notebook = new Product('Dell', 1000);

// распечатаем данные объекты
debug($book);
echo '<br>';
debug($notebook);

// получаем информацию о продукте с помощью метода getProduct()
echo $book -> getProduct();
echo $notebook -> getProduct();
?>
Выведет:
Product Object
(
[name] => Три мушкетера
[price] => 20
)

Product Object
(
[name] => Dell
[price] => 1000
)
-----------------------------------------------------
О товаре:
Наименование: Три мушкетера
Цена: 20
Кол-во страниц: 1000
-----------------------------------------------------
О товаре:
Наименование: Dell
Цена: 1000





В результате у нас выводится информация, общая для всех типов товаров: названия товаров и их цена. Специфичная информация каждого конкретного товара не выводится.


Поскольку у нас два типа товаров (ноутбук и книги), то есть смысл создать два дочерних класса: NotebookProduct и BookProduct.


Создаем дочерний класс NotebookProduct и добавим в него специфичные свойства, в нашем случае - $cpu.


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

В этом случае все методы и свойства родительского класса Product - наследуются и они нам доступны.

Чтобы получить специфичные свойства и методы - опишем их в дочернем классе NotebookProduct. Объявим свойство $cpu - специфическое свойство для Notebook. В классе Product не было этого свойства, а в классе NotebookProduct мы его добавили - тем самым расширили класс Product.

Также добавим метод getCpu().


При создании объекта нам необходимо заполнить свойства значением. Для этого напишем конструктор (__construct).

Когда мы определяем метод с тем же названием (__construct), что и в родительском классе, то мы его перезаписываем (переопределяем), то есть, теперь будет работать этот метод, а не метод в родительском классе. Если мы хотим получить ту же самую функциональность, мы должны объявить те же самые параметры из родительского класса плюс добавить наши параметры: $name,$price плюс $cpu.



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




Для того, чтобы не дублировать код, используем ключевое слово parent и оператор разрешения области видимости "::".

С помощью ключевого слова parent (parent - это слово указывает на родительский класс) и оператора разрешения области видимости "::" мы обращаемся к родительскому классу и вызваем нужный нам метод (__construct), который требует два параметра $name и $price:
parent::__construct($name, $price).


Затем дописываем нужную нам функциональность (добавляем наш параметр):

$this->cpu=$cpu .

Теперь наш конструктор (перезаписанный) вызывает сначала родительский конструктор, который отработает, и затем будет отработывать добавленный нами код.


Аналогично переопределяем родительский метод getProduct():

Вызываем родительскую функциональность:

parent::getProduct()

- и сохраняем ее в переменную $out,

и далее дописываем переменную $out нашей новой функциональностью (информацией о процессоре)

$out .= "Процессор: {$this->cpu}<br>"

- и возвращаем переменную $out.



Файл NotebookProduct.php


-- файл NotebookProduct.php --

<?php

// создаем дочерний класс NotebookProduct
// добавляем специфичные свойства
// для того, что-бы один класс мог наследовать другой класс,
// ипользуется ключевое слово (extends - расширять),
// и класс, который расширяем - Product
class NotebookProduct extends Product
{
// специфическое свойство для Notebook (мы расширили класс Product)
public $cpu;

// когда мы определяем метод с тем же названием, что и в родительском классе,
// то мы его перезаписываем (переопределяем),
// то есть, теперь будет работать этод метод, а не метод в родительском классе
// мы должны объявить те же самые параметры из родительского класса
// плюс добавить наши параметры
public function __construct($name, $price, $cpu)
{
//$this->name=$name; // параметры из родительского класса
//$this->price=$price;

// с помощью ключевого слова (parent - это слово указывает на
// родительский класс) и оператора (:: - разрешение области видимости)
// мы обратились к родительскому классу и вызвали нужный
// нам метод (__construct), который требует два параметра $name и $price
parent :: __construct($name, $price);

// дописываем нужную нам функциональность (добавляем наш параметр)
$this -> cpu = $cpu ;
}

// аналогично переопределяем родительский метод getProduct()
public function getProduct()
{
// строки из метода (getProduct() класса Product) переносим
// сюда и присваиваем переменной $out
$out = parent :: getProduct();
// дописываем переменную $out нашей новой функциональностью
$out .= "Процессор: {$this -> cpu}<br>" ;
// возвращаем переменную $out
return $out;
}

// метод getCpu()
public function getCpu()
{
return $this -> cpu;
}
}
?>





Тоже самое сделаем и для дочернего класса BookProduct:


Файл BookProduct.php


-- файл BookProduct.php --

<?php

class BookProduct extends Product
{
public $numPages;

public function __construct($name, $price, $numPages)
{
parent :: __construct($name, $price);
$this -> numPages = $numPages;
}

public function getProduct()
{
$out = parent :: getProduct();
$out .= "Кол-во страниц:: {$this -> cpu}<br>" ;
return $out;
}

public function getNumPeges()
{
return $this ->numPages ;
}
}
?>





В итоге мы получили два класса NotebookProduct и BookProduct, которые расширяют родительский класс Product.

В индексном файле подключаем наши классы и создаем объекты уже этих классов и передаем им параметры из соответствующих конструкторов.


Файл index.php


-- файл index.php --

<?php
error_reporting(-1);

require_once 'classes/Product.php';
// подключаем класс NotebookProduct
require_once 'classes/NotebookProduct.php';
// подключаем класс BookProduct
require_once'classes/BookProduct.php';

function debug($data)
{
echo '<pre>' . print_r($data, 1 ) . '</pre>';
}

// создаем объект класса BookProduct и передаем параметры из конструктора BookProduct
$book = new BookProduct('Три мушкетера', 20, 1000);

// создаем объект класса NotebookProduct и передаем параметры из конструктора NotebookProduct
$notebook = new NotebookProduct('Dell', 1000, 'Intel');

// распечатаем данные объекты
debug($book);
echo '<br>';
debug($notebook);

// получаем информацию о продукте с помощью метода getProduct()
echo $book -> getProduct();
echo $notebook -> getProduct();
?>
Получим:
BookProduct Object
(
[numPages] => 1000
[name] => Три мушкетера
[price] => 20
)
NotebookProduct Object
(
[cpu] => Intel
[name] => Dell
[price] => 1000
)
--------------------------------------------------------------------------------
О товаре:
Наименование: Три мушкетера
Цена: 20
Кол-во страниц: 1000
--------------------------------------------------------------------------------
О товаре:
Наименование: Dell
Цена: 1000
Процессор: Intel





- В результате получаем вместо двух объектов класса Product, конкретные объекты класса BookProduct и класса NotebookProduct.

Никаких пустых свойств: для книжки - cpu и для ноутбука - numPages здесь нет.

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

Наследовать можно один класс только от одного другого класса. Но PHP поддерживает цепочку наследований: сейчас мы наследуем класс BookProduct от класса Product (расширяем класс Product), но также мы можем создать какой-нибудь класс, который будет наследоваться от класса BookProduct (расширять класс BookProduct). Этот класс получит все свойства и методы, которые содержатся в классе BookProduct и в классе Product, то есть, он будет наследовать сразу два класса. Эта цепочка наследований не ограничена.


Содержание папки 8 ("Наследование"):


08-1






Наверх Наверх