Php поліморфізм, інкапсуляція і solid

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

Поліморфізм в PHP

Мова PHP підтримує поліморфізм в тому сенсі, що дозволяє використовувати замість примірників батьківського класу екземпляри підкласу. Справа в тому, що в кожному класі може бути присутнім тільки один метод з певним ім'ям. приклад:

// Наповнюємо масив публікацій об'єктами, похідними від Publication
$ Publications [] = new News ();
$ Publications [] = new Announcement ();

foreach ($ publications as $ publication) if ($ publication instanceof Publication) $ Publication-> do_print (); // то ми можемо сміливо виводити дані на друк
>
else // виняток або обробка помилки
>
>

Головне тут - остання частина. Саме в ній полягає суть поліморфізму. Ми використовуємо один і той же код для об'єктів різних класів.

Приклад на практиці: користувач хоче відстежити останні оновлення публікацій, причому йому не важливо, будуть це статті або новини або щось ще.

Інкапсуляція в PHP

Інкапсуляцію можна порівняти з роботою автомобіля з точки зору типового водія. Багато водіїв не розуміються в подробицях внутрішнього устрою машини, але при цьому управляють нею саме так, як було задумано. Нехай вони не знають, як влаштований двигун, гальмо або рульове керування, - існує спеціальний інтерфейс, який автоматизує і спрощує ці складні операції. Сказане також відноситься до інкапсуляції і ООП - багато подробиць "внутрішнього устрою" ховаються від користувача, що дозволяє йому зосередитися на вирішенні конкретних завдань. В ООП ця можливість забезпечується класами, об'єктами і різними засобами вираження ієрархічних зв'язків між ними.

У програмному сенсі цього слова, інкапсуляція - це приховування змінних в класі від користувача. Тобто всі змінні (властивості) класу Ви робите прихованими (private), а методи відкритими (public). Тобто можна буде взаємодіяти з властивостями класу через методи.
Красу даного підходу в тому, що в методах можна вставити код для перевірки будь-яких помилок, і потім про них не думати, коли викликається метод.

відносно SOLID

Хочеться внести ясність в приципом Liskov substitution і Dependency inversion, тому що теоретично складно зрозуміти в чому їхня відмінність, але я спробую.

abstract class Publication <
final protected function getId ()id;>
>

class News extends Publication public function printId () echo 'News ID:'. $ This-> getId ();
>
>
class Article extends Publication public function printId () echo 'Article ID:'. $ This-> getId ();
>
>

Liskov substitution говорить:

"Функції, які використовують базовий тип, повинні мати можливість використовувати підтипи базового типу, не знаючи про це." - означає, що якщо ми викликаємо метод певного класу, то цей клас повинен бути заміняємо (поліморфізм):

"Підкласи не можуть заміщати поведінки базових класів. Підтипи повинні доповнювати базові типи." - означає, що ми повинні розширювати базовий клас (використовуючи extend), але перевизначати методи базового класу можна (інкапсуляція + тому ми написали final. См. Вище).

Dependency inversion говорить:

"Залежності всередині системи будуються на основі абстракцій" - означає, що клас Publication повинен бути абстрактним або інтерфейсом, і потім саме його потрібно передавати у функції (поліморфізм - див. Вище виклики printPublicationId).

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