Абстрактні класи, частина 2 – Абстрактні класи та інтерфейси
У попередній публікації цієї серії я пройшов через:
- основи абстрактних класів,
- як їх реалізувати,
- і надав робочі приклади коду.
І хоча я вважаю, що розуміння абстрактних класів є ключовим у закладанні міцної основи для об’єктно-орієнтованого програмування, я часто бачу, що це може заплутати, коли справа доходить до порівняння їх з інтерфейсами та знання того, коли їх використовувати.
Абстрактні класи та інтерфейси
Тож у цій публікації я збираюся поділитися:
- коротке оновлення інформації про інтерфейси,
- що таке абстрактні класи,
- а потім як визначити, коли використовувати одне замість іншого.
Ця стаття не повинна бути інтенсивною програмуванням, але вона має допомогти зрозуміти, коли писати код певного типу, щоб краще організувати ваші проекти.
1 Інтерфейси
Пам’ятайте, що коли йдеться про інтерфейси, ми також використовуємо термін «програмування для інтерфейсу», маючи на увазі, що інтерфейс визначає методи, які клас повинен реалізувати, щоб виконати «контракт» із зазначеним інтерфейсом.
Код, використаний для демонстрації базового інтерфейсу:
<?php
interface iCache
{
public function set($key, $value);
public function get($key);
public function has($key);
}
Але пам’ятайте, що мета інтерфейсу полягає не в тому, щоб визначати після написання коду. Натомість це інструмент, який використовується для розробки того, що класи мають реалізувати, якщо вони слідують певній парадигмі або мають вимагати певного набору функцій.
Тобто, якщо ви збираєтеся розробляти набір класів, які працюють із кешуванням, ви не пишете класи спочатку. Спочатку ви пишете інтерфейс, а потім класи реалізують цей інтерфейс.
Ідея полягає в тому, що будь-який клас, який реалізує інтерфейс, гарантовано матиме ці функції.
2 Конспект Заняття
З іншого боку, абстрактні класи дозволяють нам робити дві речі:
- реалізувати функціональні можливості, які можуть використовуватися підкласами,
- реалізувати сигнатури методів, які підкласи повинні реалізувати.
Спочатку це може здатися трохи невідповідним, але подумайте про це:
Якщо у вас є клас певного типу, який матиме послідовну функціональність незалежно від підкласу, функціональність переходить до абстрактного класу. Коли інші методи потребують реалізації методу, ви просто надаєте підпис методу та позначаєте його як abstract.
Ось приклад із попереднього допису:
Тепер ми всі наздоганяємо попередні приклади та попередні речі, на яких нам потрібно зосередитися щодо інтерфейсів та абстрактних класів, але для деяких це все ще не дає великої ясності.
Зокрема, це все ще не відповідає на питання: як ми вирішуємо, коли використовувати абстрактний клас, а коли використовувати інтерфейс?
На перший погляд це може здатися трохи заплутаним, але є кілька речей, які допоможуть прийняти рішення.
Коли ми використовуємо кожен?
Пам’ятайте, що коли йдеться про об’єктно-орієнтоване програмування, ми можемо розбити його на три різні способи:
- Класи представляють річ. Ви можете вважати це іменником.
- Атрибути або властивості схожі на прикметники. Вони описують об’єкт або щось, що об’єкт може містити.
- Методи або функції схожі на дієслова. Вони описують те, що можуть робити їхні заперечення.
Тепер, коли мова йде про інтерфейс, подумайте про те, що робить інтерфейс: він описує, без реалізації, що може робити об’єкт. А коли мова йде про абстрактний клас, він описує, чим є об’єкт під час виконання.
Іншими словами, правильне емпіричне правило полягає в тому, що якщо вам потрібно забезпечити набір поведінки для об’єкта, інтерфейс – це шлях. Якщо вам потрібно описати, що таке об’єкт, використовуйте абстрактний клас.
Для абстрактних класів я б також пішов далі і сказав, що це допомагає описати базовий рівень даних, який описує об’єкт або те, що він може зберігати на додаток до базового рівня функціональності.
Є приклад?
Як і у випадку з більшістю вмісту в кожній із цих публікацій, я намагаюся наводити приклади, навіть якщо це не зроблено спеціально в коді. Можливо, це допоможе пояснити це ще більше:
- Інтерфейси не мають реалізації. Вони гарантують лише те, що зробить клас.
- Абстрактні класи повинні мати базовий рівень реалізації. Це має відображати те, що може містити та робити клас, але не повне. Вони вимагають трохи більшої реалізації від підкласу.
Коли ви працюєте з об’єктно-орієнтованим кодом, я сподіваюся, це допоможе надати деякі вказівки щодо того, коли що використовувати. Якщо ні, не соромтеся залишити коментар (те, на що учасники мають дозвіл :).
Крім того, ми побачимо це на практиці, коли дійдемо до написання об’єктно-орієнтованого коду (особливо для WordPress, але не завжди).