Перейти к основному содержимому
Модуль 4 · Урок 1 из 27/14 в курсе~15 min
Уроки модуля (1/2)

Интерфейсы

Хотя абстрактные классы могут содержать как частично реализованный код, так и поля экземпляров, интерфейсы в Java представляют собой контракты чистого поведения. Интерфейс определяет, что класс должен делать, но не то, как он это делает.

Это позволяет полностью отделить определение операций от их фактической реализации.

Определение интерфейса (interface)

Мы используем ключевое слово interface. Все методы, объявленные в интерфейсе, неявно являются public и abstract (указывать их не нужно):

Java
interface Drivable {
    void startEngine();
    void stopEngine();
}

Реализация интерфейса (implements)

Класс реализует интерфейс с использованием ключевого слова implements и обязан предоставить реализацию (с телом) для всех определенных методов:

Java
class Motorcycle implements Drivable {
    @Override
    public void startEngine() {
        System.out.println("Rombo del motore acceso!");
    }

    @Override
    public void stopEngine() {
        System.out.println("Motore spento.");
    }
}

Преимущества интерфейсов

  1. Множественное наследование. В Java класс может расширять только один родительский класс (одиночное наследование), но он может реализовывать несколько интерфейсов одновременно.
    Java
    class HybridCar implements Drivable, Chargeable { ... }
  2. Развязка. Вы можете определять переменные, используя тип интерфейса. Такой переменной можно присвоить любой объект, реализующий этот интерфейс.
    Java
    Drivable vehicle = new Motorcycle();
    vehicle.startEngine();

Константы в интерфейсах

В интерфейсах можно объявлять поля. Эти поля неявно являются public static final (что означает константы класса), даже если вы не укажете эти модификаторы. Следовательно, они должны быть инициализированы сразу после объявления:

Java
interface PhysicsConstants {
    double GRAVITY = 9.81; // Implicitly public static final
}

Методы по умолчанию (default)

Начиная с Java 8, внутри интерфейса можно определять методы с реализацией по умолчанию, используя ключевое слово default. Эти методы не заставляют реализующие классы переопределять их, обеспечивая резервное поведение:

Java
interface Logger {
    void log(String message);

    // Default method with a body
    default void logError(String message) {
        log("ERROR: " + message);
    }
}

Попробуйте сами

Упражнение#java.m4.l1.e1
Попыток: 0Загрузка…

Создайте интерфейс Flyable с помощью метода void Fly(). Затем реализуйте класс Bird, который реализует Flyable и выводит Flying на экран.

Загрузка редактора…
Показать подсказку

В Flyable напишите `void Fly();`. В классе Bird реализуйте метод, пометив его `@Override public void Fly() { System.out.println('Flying'); }`.

Решение доступно после 3 попыток

Упражнение#java.m4.l1.e2
Попыток: 0Загрузка…

Определите интерфейс Drawable с помощью метода void draw(). Затем реализуйте класс Rectangle, который реализует Drawable и печатает Drawing Rectangle.

Загрузка редактора…
Показать подсказку

Определите `void draw();` в интерфейсе. В Rectangle используйте `@Override public void draw() { System.out.println('Drawing Rectangle'); }`.

Решение доступно после 3 попыток

Упражнение#java.m4.l1.e3
Попыток: 0Загрузка…

Завершите интерфейс Swimmable, определив метод void swim(). Затем завершите класс Duck, чтобы он реализовывал как Flyable, так и Swimmable, напечатав «Полет в методе Fly()» и «Плавание в методе плавания()».

Загрузка редактора…
Показать подсказку

Объявите `void swim();` внутри Swimmable. Объявите класс Duck, реализующий Flyable, Swimmable и реализуйте оба метода, печатающие запрошенные строки.

Решение доступно после 3 попыток