Назад Зміст Вперед

8.2. Інтерфейси

Інтерфейси

Інтерфейси дуже схожі на абстрактні класи. Він оголошується так само, як і клас, тільки використовується ключове слово interface.
Наприклад:

interface Drawable
{
 void draw();
}
interface HasValue
{
 int getValue();
}
1) Замість слова class пишемо interface.
2) Містить тільки абстрактні методи (слово abstract писати не потрібно).
3) Насправді у інтерфейсів всі методи - public.
interface Element extends Drawable, HasValue
{
int getX();
int getY();
}
Інтерфейс може успадковуватися тільки від інтерфейсів.

Інтерфейсів-батьків може бути багато.
class abstract ChessItem implements Drawable,HasValue
{
 private int x, y, value;
 public int getValue()
 {
 return value;
 }
 public int getX()
 {
 return x;
 }
 public int getY()
 {
 return y;
 }
}
Клас може успадковуватися від декількох інтерфейсів (і тільки від одного класу). При цьому використовується ключове слово implements.

Клас ChessItem оголошений абстрактним: він реалізував всі успадковані методи, крім draw.

Тобто клас ChessItem містить один абстрактний метод: draw ().

Оголошення інтерфейсів
Загальна форма інтерфейсу:
доступ interface ім'я
{
   тип_повернення ім'я_методу1(список параметрів);
   тип_повернення ім'я_методу2(список параметрів);
   тип ім'я_кінцевої_змінної1=значення;
   тип ім'я_кінцевої_змінної2=значення;
...
   тип_повернення ім'я_методуN(список параметрів);
   тип ім'я_кінцевої_змінноїN=значення;
}
Якщо визначення не містить ніякого модифікатора доступу, використовується доступ за замовчуванням, а інтерфейс доступний тільки іншим членам того пакету, в якому він оголошений. Якщо інтерфейс оголошений як public, він може бути використаний в будь-якому іншому коді. В цьому випадку інтерфейс повинен бути єдиним відкритим інтерфейсом, оголошеним в файлі, а ім'я цього файлу повинно збігатися з ім'ям інтерфейсу. У наведеній вище загальній формі вказане ім'я позначає конкретне ім'я інтерфейсу, яким може бути будь-який допустимий ідентифікатор. Зверніть увагу на те, що методи, які оголошуються не містять тіла. Їх оголошення завершуються списком параметрів, за яким слідує крапка з комою. По суті, вони є абстрактними методами. Кожен клас, який включає в себе інтерфейс, повинен реалізувати всі його методи.

Як випливає з наведеної вище загальної форми, в оголошеннях інтерфейсів можуть бути оголошені змінні. Вони неявно оголошуються як final і static, тобто їх не можна змінити в класі, що реалізує інтерфейс. Крім того, вони повинні бути ініційовані. Всі методи і змінні неявно оголошуються в інтерфейсі як public.

Приклад оголошення інтерфейсу: оголошується простий інтерфейс, який містить один метод callback (), який приймає єдиний цілочисельний параметр 
interface Callback{
    void callback(int param);
}

Часткова реалізація

Якщо клас включає в себе інтерфейс, але не повністю реалізує його методи, то він повинен бути оголошений як abstract
abstract class Incomplete implements Callback {
int а, b;
void show () {
    System.out.println(a+""+b);
}
//...
}
В даному прикладі коду клас Incomplete не реалізує метод callback (), тому він повинен бути оголошений як абстрактний. Будь-який клас, що успадковується від класу Incomplete, повинен реалізовувати метод callback () або бути також оголошеним як abstract.

Застосування статичних методів у інтерфейсі

ім'я_інтерфейсу.ім'я_статичного_методу

Приклад коду: введення статичного методу getDefaultNшnЬer () в інтерфейс MyIF. Цей метод повертає нульове значення.
public interface MyI F {
// Оголошення звичайного методу в інтерфейсі
// Він НЕ надає реалізацію за замовчуванням 
int getNumber () ;
//Оголошення методу за замовчуванням
default String getString(){
return "Об'єкт типу String за замовчуванням" ;
//Оголошення статичного методу в інтерфейсі
static int getDefaultNumber(){
return 0;

Метод getDefaultNumber ( ) може бути викликаний наступним способом:
int defNum = MyIF.getDefaultNumber();
Читати більше Шилдт Г., ст.247
У інтерфейсів є дві переваги в порівнянні з класами:
1. Відділення «опису методів» від їх реалізації. 
Раніше, якщо потрібно було викликати методи свого класу з інших класів, то їх потрібно позначити ключовим словом public. Щоб якісь методи могли викликати тільки з свого ж класу, їх потрібно позначати ключовим словом private. Іншими словами ми ділимо методи класу на дві категорії: «для всіх» і «тільки для своїх». За допомогою інтерфейсів, цей поділ можна збільшити ще більше. Зробити спеціальний «клас для всіх», і другий «клас для своїх», який успадкується від першого. Тобто, зробили інтерфейс і клас, який унаслідували від цього інтерфейсу. Один і той самий інтерфейс може реалізовувати (успадковувати) різні класи. І у кожного може бути своя власна поведінка.

2. Множинне наслідування. 
Інтерфейс може мати кілька інтерфейсів-батьків. Клас може мати кілька інтерфейсів-батьків і тільки один клас-батько.

Клас - це частіше за все модель якогось конкретного об'єкта. Інтерфейс більше відповідає не об'єкту, а їх здібностям або ролям.
Наприклад, такі речі, як машина, велосипед, мотоцикл і колесо найкраще представити у вигляді класів та об'єктів. А такі їх здатності як «можу їздити», «можу перевозити людей», «можу стояти» - краще представити у вигляді інтерфейсів. 
Наприклад:
interface Moveable
{
void move(String newAddress);
}
- відповідає здатності рухатися.
interface Driveable
{
void drive(Driver driver);
}
- відповідає здатності керувати водієм.
interface Transport
{
void addStaff(Object staff);
Object removeStaff();
}
- відповідає здатності перевозити вантажі.
class Wheel implements Moveable
{
...
}
- клас «колесо». Має здатність рухатися.
class Car implements Moveable, Driveable,   Transport
{
...
}
- клас «машина». Має здатність рухатися, керувати людиною і перевозити вантажі.
class Skateboard implements Moveable, Driveable
{
...
}
- клас «скейтборд». Має здатність рухатися і керувати людиною.

Суть інтерфейсів в тому, не потрібно писати код для взаємодії з усіма класами, достатньо взаємодіяти з їх ролями (інтерфейсами).

Реалізація інтерфейсів

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

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

1) Успадкуватися від них.
2) Реалізувати оголошені в них методи.
3) Методи повинні робити те, для чого вони призначені.

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

Різниця між інтерфейсом та абстрактним класом

Абстрактні класи використовуються тільки тоді, коли є "is a" тип відносин; інтерфейси можуть бути реалізовані класами які не пов'язані один з одним. 

Абстрактний клас може реалізовувати методи; інтерфейс не може реалізовувати методи. 

Інтерфейс може тільки описувати константи і методи, але не реалізовувати їх. Всі методи інтерфейсу за замовчуванням є публічними (public) та абстрактними (abstract), а поля - public static final.

Отже,
НАСЛІДУВАННЯ
Абстрактний клас може успадковуватися тільки від одного класу і будь-якої кількості інтерфейсів.
Інтерфейс не може успадковуватися від класів, але може від будь-якої кількості інтерфейсів.
АБСТРАКТНІ МЕТОДИ
Абстрактний клас може містити абстрактні методи. Але може і не містити їх взагалі.
Всі методи інтерфейсу - абстрактні - не містять реалізації. Інтерфейс може не містити ніяких методів взагалі.
МЕТОДИ З РЕАЛІЗАЦІЄЮ
Абстрактний клас може містити методи з реалізацією.
Інтерфейс не може містити методи з реалізацією.
ДАНІ
Ніяких обмежень.
Інтерфейс містить тільки public final static дані і public abstract методи.
СТВОРЕННЯ ОБ'ЄКТА
Не можна створити об'єкт абстрактного класу.

Не можна створити об'єкт інтерфейсу.


.