— Привіт, Аміго! Хочу сьогодні тобі розповісти про причини існування інтерфейсів. Тобі дуже часто доведеться чути, що певний клас, об'єкт чи сутність підтримує певний інтерфейс. Що ж це означає – підтримувати інтерфейс?

У більш широкому значенні інтерфейс якоїсь речі – це механізм взаємодії цієї речі з іншими предметами. Наприклад, пульт від телевізора – це дистанційний інтерфейс. Собака розуміє та виконує команди — це означає, що собака підтримує голосовий інтерфейс (керування). Якщо все це підсумувати, можна сказати, що інтерфейс – це стандартизований спосіб взаємодії двох речей, і цей стандарт відомий двом сторонам. Коли людина каже собаці «сидіти», вона віддає команду відповідно до «голосового інтерфейсу управління собакою», і якщо собака виконує цю команду, то ми говоримо, що собака підтримує цей інтерфейс.

Так само й у програмуванні. Методи – це дії над об'єктом, з його даними. І якщо клас реалізує певні методи, він «підтримує виконання» певних команд. Які переваги дає об'єднання методів в інтерфейс?

1) Кожний interface, як і class, має унікальне ім'я. Обидві сторони можуть бути на 100% впевнені, що інша сторона підтримує саме потрібний інтерфейс, а не схожий.

2) Кожен інтерфейс накладає певні обмеження на той клас, який має намір підтримувати його. Клас сам вирішує (його розробник), що він робитиме у разі виклику його методів, які він успадкував від інтерфейсу, але результат має бути в межах очікувань. Якщо ми скомандували собаці «сидіти», і вона покрутилася 5 хвилин на місці та сіла, то це – підтримка інтерфейсу. А якщо вона замість цього вчепилася вам у ногу, то про жодну підтримку тут не може бути й мови. Виконання команди не призвело до очікуваних результатів.

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

Код на Java Опис
interface Saveable
{
 void saveToMap(Map<String, Object> map);
 void loadFromMap(Map<String, Object> map);
}
— інтерфейс зі збереження/завантаження об'єкта із map’а.
interface Drawable
{
 void draw(Screen screen);
}
— інтерфейс з відтворення об'єкта всередині переданого об'єкта screen.
class PacMan implements Saveable, Drawable
{
…
}
— твій клас, що реалізує підтримку двох інтерфейсів.

Іншими словами, щоб підтримати реалізацію якогось інтерфейсу (групи інтерфейсів) у своєму класі потрібно:

1) Успадкуватися від них

2) Реалізувати оголошені у них методи

3) Методи мають робити те, для чого вони призначені.

Тоді решта коду програми, який нічого не знає про твій клас та його об'єкти, зможе успішно працювати з ним.

— А чому код може нічого не знати про мій клас?

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

— Круто! Не знав, що так можна.

— На цьому принципі засновані всі великі проєкти. Вже давно ніхто нічого не пише з нуля.

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