Модульні уроки (1/2)
Інтерфейси
Хоча абстрактні класи можуть містити як частково реалізований код, так і поля екземплярів, інтерфейси в Java є контрактами чистої поведінки. Інтерфейс визначає, що повинен уміти робити клас, але не як він це робить.
Це дозволяє повністю відокремити визначення операцій від їх фактичної реалізації.
Визначення інтерфейсу (interface)
Ми використовуємо ключове слово interface. Усі методи, оголошені в інтерфейсі, неявно мають значення public та abstract (це не потрібно вказувати):
interface Drivable {
void startEngine();
void stopEngine();
}Реалізація інтерфейсу (implements)
Клас реалізує інтерфейс за допомогою ключового слова implements і повинен забезпечити реалізацію (з тілом) для всіх визначених методів:
class Motorcycle implements Drivable {
@Override
public void startEngine() {
System.out.println("Rombo del motore acceso!");
}
@Override
public void stopEngine() {
System.out.println("Motore spento.");
}
}Переваги інтерфейсів
- Множинне успадкування: у Java клас може розширювати тільки один батьківський клас (єдине успадкування), але він може реалізувати кілька інтерфейсів одночасно.
Java
class HybridCar implements Drivable, Chargeable { ... } - Відокремлення: Ви можете визначати змінні за допомогою типу інтерфейсу. Будь-який об’єкт, який реалізує цей інтерфейс, може бути призначений такій змінній.
Java
Drivable vehicle = new Motorcycle(); vehicle.startEngine();
Константи в інтерфейсах
В інтерфейсах можна оголошувати поля. Ці поля неявно мають значення public static final (що означає константи класу), навіть якщо ви не вкажете ці модифікатори. Отже, вони повинні бути ініціалізовані відразу після оголошення:
interface PhysicsConstants {
double GRAVITY = 9.81; // Implicitly public static final
}Методи за замовчуванням (default)
Починаючи з Java 8, можна визначати методи з реалізацією за замовчуванням всередині інтерфейсу за допомогою ключового слова default. Ці методи не змушують класи реалізації перевизначати їх, забезпечуючи резервну поведінку:
interface Logger {
void log(String message);
// Default method with a body
default void logError(String message) {
log("ERROR: " + message);
}
}Спробуйте самі
Створіть інтерфейс Flyable за допомогою методу void fly(). Потім реалізуйте клас Bird, який реалізує Flyable і друкує Flying на екрані.
Показати підказку
У Flyable напишіть `void fly();`. У класі Bird реалізуйте метод, позначивши його за допомогою `@Override public void fly() { System.out.println('Flying'); }`.
Рішення доступне після 3 спроб
Визначте інтерфейс Drawable за допомогою методу void draw(). Потім реалізуйте клас Rectangle, який реалізує Drawable і друкує Drawing Rectangle.
Показати підказку
Визначте `void draw();` в інтерфейсі. У Rectangle використовуйте `@Override public void draw() { System.out.println('Drawing Rectangle'); }`.
Рішення доступне після 3 спроб
Доповніть інтерфейс Swimmable, визначивши метод void swim(). Потім завершіть клас Duck, щоб він реалізував і Flyable, і Swimmable, надрукувавши Flying у методі fly() і Swimming у методі swim().
Показати підказку
Оголошіть `void swim();` всередині Swimmable. Оголошіть `class Duck implements Flyable, Swimmable` та реалізуйте обидва методи, друкуючи запитані рядки.
Рішення доступне після 3 спроб