Введение в наследование в ООП PHP.

Наследование. Введение



В папке с уроком создадим класс продуктов - class Product.


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


07-1



Класс продуктов будет описывать различные типы продуктов интернет-магазина. Например, наш интернет-магазин будет продавать ноутбуки и книги. У этих товаров абсолютно разный набор свойств (у ноутбуков есть процессор, а у книг есть страницы).
Соответственно, мы можем отталкиваться от таких характеристик - наименование процессора и количества страниц. Но, вместе с тем, у каждого из товаров есть какие-то и общие свойства. Например - наименование товара и цена товара.

Определим в классе class Product свойства.
Общие свойства:
- public $name; - наименование товара,
- public $price; - цена товара.
Специфичные свойства, зависящие от того или иного товара
- public $cpu; - процессор,
- public $numPages; - количество страниц.


В конструкторе будем задавать свойства, при этом $name и $price - общие для всех товаров, а $cpu и $numPages - свойства, которые зависят от того или иного товара. Поэтому, по умолчанию, зададим: $cpu = null, $numPages = null. Это нужно для того, чтобы при создании экземпляра класса (товара) и передачи ему параметров, не передавались параметры, которых не должно быть в данном товаре (например, у книг нет процессора, у ноутбуков нет страниц и т. д.).
Соответственно, если мы будем создавать экземпляр класса (товар) "ноутбук", то мы передадим три параметра -
без количества страниц ($numPages = null).


Чтобы получить отдельно значения свойств этих объектов ($cpu и $numPages), создадим соответствующие методы: getCpu и getNumpeges.
(Методы, которые начинаются с get, называются гетерами).
С помощью метода getProduct получим в переменной $out информацию о товаре.
Чтобы понять, у какого объекта вызвать метод getProduct, передадим методу параметр по умолчанию $type = 'notebook' - это решение называется "костыль".
Далее используем условие.


Файл Product.php


-- файл Product.php --

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

// специфичные свойства, зависящие от того или иного товара
public $cpu; // процессор
public $numPages; // количество страниц

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

}

// получаем отдельно значение свойства (cpu) методом (getCpu());
// метод будет возвращать значение свойства (cpu)
public function getCpu()
{
return $this -> cpu;
}

// получаем отдельно значение свойства (numPages) методом (getNumPages());
// метод будет возвращать значение свойства (numPages)
public function getNumpeges()
{
return $this -> numPages;
}

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

// если ($type == 'notebook')
if($type == 'notebook')
{
// то в переменную ($out) допишем строку (" Процессор: {$this->cpu}")
$out .= " Процессор: {$this->cpu} <br> ";
// иначе:
} else {
// в переменную ($out) допишем строку ("Кол-во страниц:{$this->numPages}")
$out .= "Кол-во страниц: {$this->numPages} <br> ";
}
// возвращаем сформированную переменную $out
return $out;
}
}
?>





В индексном файле подключим наш класс Product и создадим экземпляры данного класса $book и $notebook.


Файл index.php


-- файл index.php --

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

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

// Создадим экземпляр класса Product (ноутбук)
// чевертый параметр нам не нужен, поэтому мы его не указываем
$notebook = new Product('Dell', 1000, 'intel');

// распечатаем данные объекты с помощью функции debug($data)
debug($book);
echo '<br>';
debug($notebook);

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

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





Мы написали класс, который выводит информацию о том или ином продукте, при этом основываясь на его типе.

В данном классе имеются проблемы:
- необходимость использования условия "if - else" - для большого количества товаров это неприемлемо.
- у каждого из товаров будут присутствовать свойства, принадлежащие другим типам товаров (ноутбук -> количество страниц, у книги -> процессор и т. д.).
- также у нас могут быть специфичные методы для каждого из типов товаров - это позволяет попытаться, например, получить количество сраниц (numPages) у ноутбука.
Есть два разных объекта, и получается, чтобы решить эти проблемы, нам придется писать два разных класса под каждый из этих объектов, что также неприемлемо из-за дублирования кода.


Эти проблемы решаются с помощью такого принципа в ООП, как наследование.


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


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

А все остальные классы мы можем наследовать от этого самого базового класса.

Соответственно мы устанавливаем некую связь: родительский - дочерние классы. Базовый класс будет родительским, а те классы, которые его наследуют будут дочерними. При этом, в дочернем классе, к функциональности родительского класса (который часто называют суперклассом) мы можем добавлять новую функциональность. Фактически дочерние классы будут расширять(наследовать) родительский.






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