Уроки модуля (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, напечатав «Полет в методе Fly()» и «Плавание в методе плавания()».
Показать подсказку
Объявите `void swim();` внутри Swimmable. Объявите класс Duck, реализующий Flyable, Swimmable и реализуйте оба метода, печатающие запрошенные строки.
Решение доступно после 3 попыток