Спадкування в обєктно-орієнтованому програмуванні на PHP

29

Від автора: формуючи структуру майбутнього проекту, рідко вдається описати логіку одним єдиним класом. Як правило, створюється ціла ієрархія з різних класів, кожен з яких відповідає за функціонал елементу майбутнього додатки. При цьому для забезпечення більшої гнучкості і універсальності, як привило в основі логічної структури, розташовуються класи які задають основний функціонал і є батьківськими для всіх наступних. Тому в даній статті ми з Вами розглянемо таке поняття як спадкування в ООП в PHP.

Взагалі є три основних, найголовніших принципи ООП на PHP — наслідування, інкапсуляція, поліморфізм які, по суті, визначають всю суть даного підходу, і, як Ви зрозуміли перший з них, ми розглядаємо сьогодні, а про решту поговоримо в наступних статтях.

Отже, спадкування в об’єктно-орієнтованому програмуванні на PHP – це спеціальний механізм, завдяки якому кілька класів формуються з одного базового класу. При цьому базовий клас називають батьківським, а всі похідні від нього – дочірніми, або підкласами. В результаті цього дочірні класи отримують доступ до властивостей і методів батьківського, що дуже зручно, якщо необхідно винести якийсь загальний для деяких класів функціонал. Крім того підкласи, звичайно ж можуть утримувати свої власні методи і властивості і в цьому випадку можна говорити, що вони розширюють батьківський клас.

vТеперь давайте розглянемо наступний простий приклад. Припустимо, що необхідно реалізувати невеликий додаток з наступними розділами: блог, товари, користувачі (розділ користувачі, повинен тільки вивести на екран список конкретних користувачів). Таким чином, у нас є три окремі сутності, а отже для кожної з них потрібно сформувати клас, в структурі якого будуть описані методи, вибірки необхідної інформації і відображення її на екран у відповідному вигляді. Для відображення на екран може використовуватися шаблонизатор, а для зберігання інформації – сервер бази даних MySQL.

Тому давайте подивимося на можливу, спрощену структуру одного з класів:

db = new mysqli(‘localhost’,’root’,»,’my_db’);
$this->footer = «Footer Blog»;
$this->header = «Header Blog»;
}
public function getHeader() {
return $this->header;
}
public function getFooter() {
return $this->footer;
}
public function render_body() {
$statti = $this->get_content();
$str = «;
foreach($statti as $item) {
$str .= «

«;
$str .= ‘

‘.$item[‘title’].’

‘;
$str .= ‘

‘.$item[‘text’].»

«;
$str .= «

«;
}
return $str;
}
public function get_content() {
$query = «SELECT * FROM `users` WHERE active == ‘1’»;
$this->content = $this->db->query($query)->fetch_all(MYSQLI_ASSOC);
return $this->content;
}
public function show() {
return $this->getHeader().$this->render_body().$this->getFooter();
}
}
$obj = new Blog();
echo $obj->show();

Хотів би відразу ж зазначити, що клас дуже і дуже простий, в ньому не передбачена гнучкість для подальшого використання і розширення, а також не зовсім коректно описаний код, в плані використання виведення інформації на екран. Тому як все що стосується дизайну, необхідно виносити окремо, в файли шаблонів, що містять мінімум логіки. Але зараз завдання полягає в тому, що б зрозуміти суть спадкування, а значить для цього даний приклад цілком підійде.

Дивіться, описаний клас Blog, необхідний для формування структури сторінки відображення статей блогу. У методі конструкторі, здійснюється з’єднання з сервером бази даних MySQL, бо саме там розташовується збережена інформація за матеріалами. Методи getHeader() і getFooter(), повертає вміст шапки сайту і його футера відповідно. Основний вміст сторінки, формує метод get_content() і, по суті, в ньому ми бачимо виконання найпростішого запиту SQL.

Як шаблонизатора, виступає метод render_body(), хоча, це дуже гучна назва, але все ж. І, нарешті, метод show(), збирає все, воєдино, і повертає для відображення на екран. Таким чином, для відображення інформації на екран, досить створити об’єкт вищевказаного класу і відобразити на екран результат роботи методи show().

Здавалося б, все дуже просто, але нам потрібно, сформувати ще два аналогічні сторінки і по суті код їх класів, буде приблизно такою ж, за винятком методу get_content(), так як потрібно зовсім інший SQL запит, а також може відрізнятися вміст шапки і футера.

db = new mysqli(‘localhost’,’root’,»,’my_db’);
$this->footer = «Footer Users»;
$this->header = «Header Users»;
}
public function getHeader() {
return $this->header;
}
public function getFooter() {
return $this->footer;
}
public function render_body() {
$statti = $this->get_content();
$str = «;
foreach($statti as $item) {
$str .= «

«;
$str .= ‘

‘.$item[‘title’].’

‘;
$str .= ‘

‘.$item[‘text’].»

«;
$str .= «

«;
}
return $str;
}
public function get_content() {
$query = «SELECT * FROM `users` WHERE active == ‘1’»;
$this->content = $this->db->query($query)->fetch_all(MYSQLI_ASSOC);
return $this->content;
}
public function show() {
return $this->getHeader().$this->render_body().$this->getFooter();
}
}
$obj = new Blog();
echo $obj->show();

Як Ви бачите, ми практично продублювали попередній клас, що, звичайно ж, не зовсім правильно, особливо якщо нам потрібен ще один схожий розділ.

Тому, весь загальний функціонал ми можемо винести в батьківський клас, а в дочірніх, успадкованих підкласах – описати тільки унікальні дії для конкретного розділу.

db = new mysqli(‘localhost’,’root’,»,’my_db’);
}
public function getHeader() {
return $this->header;
}
public function getFooter() {
return $this->footer;
}
public function render_body() {
$statti = $this->get_content();
$str = «;
foreach($statti as $item) {
$str .= «

«;
$str .= ‘

‘.$item[‘title’].’

‘;
$str .= ‘

‘.$item[‘text’].»

«;
$str .= «

«;
}
return $str;
}
public function show() {
return $this->getHeader().$this->render_body().$this->getFooter();
}
}
class Blog extends Page {
public function __construct() {
parent::__construct();
$this->header = «Header Blog»;
$this->footer = «Footer Blog»;
}
public function get_content() {
$query = «SELECT * FROM `statti`»;
$this->content = $this->db->query($query)->fetch_all(MYSQLI_ASSOC);
return $this->content;
}
}
class User extends Page {
public function __construct() {
parent::__construct();
$this->header = «Header User»;
$this->footer = «Footer User»;
}
public function get_content() {
$query = «SELECT * FROM `user` WHERE active = ‘1’»;
$this->content = $this->db->query($query)->fetch_all(MYSQLI_ASSOC);
return $this->content;
}
}
$obj = new Blog();
echo $obj->show();

У прикладі вище, батьківський клас – це клас Page, в який винесено абсолютно весь загальний функціонал – підключення до бази даних, формування шапки і футера сайту, метод шаблонизатора і метод show(). Відповідно, для створення дочірнього класу, використовується спеціальне слово extends, при оголошенні класу. У нашому випадку класи Blog і User, успадковують функціонал батьківського класу Page, тобто розширюють його. При цьому вони отримують доступ до властивостей і методів базового класу. А значить, в їх структурі достатньо описати лише ті методи, які унікальні для конкретної сутності.

Більш того, в дочірніх класах, ми вправі змінити методи батьківського класу, тобто створювати методи з аналогічним ім’ям, але абсолютно інший реалізацією. В якості прикладу, ми бачимо перевизначено метод конструктора, в якому визначаються значення властивостей $header і $footer. При цьому якщо метод змінюється то, по суті, ми заміщаємо його код новим, а значить, якщо з об’єкта звернутися до даного методу, саме він буде викликаний на виконання. При цьому дуже часто, перевизначаючи код методи батьківського класу, необхідно звертатися до цього ж методу, але описаному в базовому класі. Що, власне, Ви і бачите у прикладі вище, у методі конструкторі. Для звернення до методу батьківського класу, необхідно використовувати зарезервоване слово parent. При цьому, звертаючись до конструктора базового класу, ми виконуємо підключення до бази даних, а після цього визначаємо значення властивостей header і footer.

Таким чином, в об’єктно-орієнтованому програмуванні спадкування в PHP, характеризується перевизначенням методів базового батьківського класу.

Ось і все про що я хотів сказати Вам в цій статті, як Ви бачите, успадкування класів дуже зручно використовувати при побудові логіки майбутнього додатки, так як завдяки йому ми можемо сформувати повноцінну ієрархію класів. Більш детально поточна тема розглянута в курсі Курс об’єктно-орієнтованого програмування (ООП PHP).

Всього Вам доброго і вдалого кодування!!!