Об’єктно-орієнтоване програмування: розуміння інтерфейсів
На цьому етапі я б сказав, що основи розуміння об’єктно-орієнтованого програмування були закладені.
Зокрема, я розглянув:
І, так, є деякі дебати щодо того, що є основою (тобто, деякі не додають поліморфізм до суміші, хоча я це роблю). Але наведені вище чотири мають створити міцну основу, на якій можна продовжувати розвивати свої навички об’єктно-орієнтованого програмування.
Є й інші, але я не думаю, що вони настільки глибокі, детальні або складні для розуміння, як деякі з вищезгаданих концепцій. Знову ж таки, різні речі даються іншим легше.
У будь-якому випадку, наступні дві теми, які важливо зрозуміти, це:
- Інтерфейси
- Абстракція
Я розповім про кожну окремо, але переконайтеся, що ви спочатку прочитали серію «Основи », оскільки дві вищезгадані теми дозволять вам покластися на них і скористатися ними.
Розпливчасто, я знаю, але дозволь мені пояснити, а потім продовжу.
Розуміння інтерфейсів
Найпоширенішим визначенням інтерфейсу, яке ви можете почути, є договір. Це не неправильно, але я думаю, що залишає бажати кращого.
Наприклад, коли ви думаєте про контракти, ви, швидше за все, думаєте про щось дуже складне, багато жаргону, складний процес отримання чогось підписаного, датованого, готового до роботи тощо.
Але коли справа доходить до інтерфейсів програмування, це насправді не так. Фактично, я б стверджував, що визначення інтерфейсів може полегшити програмування та полегшити бюрократію, оскільки це робить речі дуже чорними чи білими щодо того, що щось має реалізувати.
Кілька слів про «інтерфейси»
Наша галузь використовує слово «інтерфейс» для двох речей:
- Дизайнери та користувачі використовують термін інтерфейс, щоб описати те, що вони бачать і як вони взаємодіють із програмою. Сюди входять такі речі, як кнопки, спадні меню та інші елементи, до яких ми можемо «доторкнутися».
- Програмісти використовують цей термін для позначення того, які функції повинен реалізувати підклас, щоб відповідати інтерфейсу. Це називається «програмування для інтерфейсу».
Про останнє й піде мова в цій статті. І ні, ми не будемо використовувати типові приклади, такі як програмування для інтерфейсу Animal або щось інше. Натомість ми розглянемо, як це зробити, виходячи з реальних зразків коду.
Програмування до інтерфейсу
Ми визначаємо «програмування для інтерфейсу» як спосіб написання коду, який реалізує сигнатури функцій, визначених у зазначеному інтерфейсі.
Але що таке сигнатури методів? Простіше кажучи, сигнатури методів включають:
- ім’я імені функції,
- необхідні аргументи,
- модифікатор видимості
У контексті класу ви побачите це так:
<?php
class Cache
{
public function set($key, $value)
{
// method implementation
}
}
Легко, правда?
У наведеному вище коді ми бачимо, що функція set приймає ключ і значення, які будуть використані, і функція доступна для будь-якого об’єкта, який має посилання на клас.
Але інтерфейси також можуть включати це. Однак є застереження: інтерфейси не мають реалізації методів.
Тож замість чогось подібного:
<?php
class Cache
{
public function set($key, $value) {
set_transient($key, $value);
}
}
Ви побачите це:
<?php
interface iCache
{
public function set($key, $value);
public function get($key);
public function has($key);
}
Але в наведеному вище коді також є кілька тонкощів, на які варто звернути увагу.
- Цей код не визначає його як клас. Замість цього він називає це інтерфейсом.
- Ім’я класу має префікс «i», щоб вказати, що це інтерфейс. Це не обов’язково; це конвенція.
- Метод не має реалізації. На ньому немає нічого, крім підпису.
Коли ми створюємо інтерфейс, ми говоримо, як згадувалося вище, що будь-який клас, який реалізує інтерфейс, буде визначати методи, які він включає.
Отже, якби ми об’єднали все, що ми бачили вище, остаточна реалізація виглядала б так (хоча в ідеалі ми б зберегли це в окремих файлах):
<?php
interface iCache {
public function set($key, $value);
public function get($key);
public function has($key);
}
public class SimpleCache implemnents iCache
{
public function set($key, $value)
{
set_transient($key, $value, DAY_IN_SECONDS);
}
public function get($key)
{
if (!$this->has($key))
{
return false;
}
return get_transient($key);
}
public function has($key)
{
return false !== get_transient($key);
}
}
Ось як поєднуються інтерфейси та класи.
Це воно?
Простіше кажучи, так. Але зі свого досвіду я переконався, що це щось більше, ніж просто визначення методів і їх впровадження.
Часто легко визначити класи, потім визначити інтерфейс, а потім реалізувати інтерфейс. Але це зовсім назад. Натомість нам потрібно більш стратегічно думати про свою роботу.
Замість того, щоб повертатися до інтерфейсу, який повністю перешкоджає меті, нам потрібно почати широко, щоб наші класи могли спеціалізуватися на тому, що вони роблять, одночасно реалізовуючи функціональні можливості, які є спільними не лише для цього класу, але й для інших класів, яким може знадобитися така сама функціональність.
Використовуючи приклад вище, ми можемо мати SimpleCache, TransientCache або інший тип кешу. Незалежно від того, який тип кешу ми реалізуємо, вони реалізують інтерфейс, а функціональні можливості залишаються за класом, який реалізує інтерфейс.
Таким чином, ми визначаємо, як може виглядати кеш на високому рівні, але класи реалізації визначатимуть, як саме вони функціонують.
Якщо ви розробник WordPress і бажаєте навчитися створювати щось поверх програми за допомогою практичних об’єктно-орієнтованих методів, тоді чому б не приєднатися до сайту?