Menu

Интерфейсы в Java: определение контрактов и implements

Что такое интерфейс в Java, как его определить и реализовать, методы default и static, и чем интерфейсы отличаются от абстрактных классов.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Интерфейс — это контракт

Интерфейс объявляет, что класс может делать, не говоря, как. Это список сигнатур методов, которые любой реализующий класс обязуется выполнить. Суть в развязке: код может работать с типом интерфейса и не заботиться о том, какой конкретный класс стоит за ним.

Circle implements Shape означает, что Circle должен определить area и perimeter. Как только он это делает, Circle является Shape и может храниться в переменной типа Shape.

Много классов, один тип

Сила проявляется, когда несколько несвязанных классов реализуют один и тот же интерфейс. Код, написанный под Shape, обрабатывает их все:

Цикл никогда не спрашивает «это Circle или Rectangle?» — он просто вызывает area() и доверяет контракту. Добавление Triangle позже не потребует здесь никаких изменений.

Реализация нескольких интерфейсов

Класс наследует только один класс, но может реализовывать любое число интерфейсов — именно так Java безопасно осуществляет «множественное наследование» поведения:

Перечислите интерфейсы через запятую после implements. Класс должен удовлетворять им всем.

Методы default и static

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

Методы default позволяют интерфейсу развиваться — добавлять метод, не ломая каждую существующую реализацию. Метод интерфейса static, напротив, — это утилита, которую вы вызываете у самого интерфейса, как Comparator.naturalOrder().

Константы

Поля в интерфейсе неявно являются public static final — это константы, а не состояние экземпляра:

interface Physics {
    double GRAVITY = 9.81;   // automatically public static final
}

Интерфейсы традиционно не хранят состояния отдельного объекта; отсутствие полей экземпляра — часть того, что отличает их от классов.

Функциональные интерфейсы

Интерфейс ровно с одним абстрактным методом является функциональным интерфейсом, и его можно реализовать лямбда-выражением вместо целого класса:

Это основа лямбд Java и типов из java.util.function (Function, Predicate, Supplier и им подобных). Аннотация @FunctionalInterface делает намерение явным и позволяет компилятору следить за соблюдением правила единственного метода.

Интерфейс против абстрактного класса

Оба позволяют программировать на уровне абстракции, так когда же выбирать тот или иной?

  • Интерфейс — возможность, которую могут разделять несвязанные классы. И Bird, и Airplane могут быть Flyable. Класс может реализовать множество интерфейсов. Без состояния экземпляра.
  • Абстрактный класс — общее состояние и код среди тесно связанных классов. И Cat, и Dog наследуют Animal, получая общие поля и частично реализованные методы. Класс наследует только один.

Распространённый шаблон сочетает их: интерфейс определяет контракт, а абстрактный класс реализует шаблонные части, чтобы конкретные подклассы заполняли лишь специфические детали.

Далее: абстрактные классы

Интерфейсы определяют поведение без состояния. Абстрактные классы находятся между интерфейсами и полноценными классами — они могут объявлять нереализованные методы и нести поля и конструкторы. Это тема следующей страницы.

Часто задаваемые вопросы

Что такое интерфейс в Java?

Интерфейс — это контракт: набор сигнатур методов (и констант), которые класс обязуется предоставить. Он говорит, что класс может делать, но не как. Класс использует ключевое слово implements, чтобы принять интерфейс, и должен предоставить тело для каждого абстрактного метода, объявленного интерфейсом. Интерфейсы позволяют использовать несвязанные между собой классы взаимозаменяемо через общий тип.

В чём разница между интерфейсом и абстрактным классом в Java?

Класс может реализовывать множество интерфейсов, но наследовать (extends) лишь один (абстрактный) класс. Интерфейсы традиционно не хранят состояния экземпляра и только объявляют поведение, тогда как абстрактный класс может иметь поля, конструкторы и частично реализованную логику. Используйте интерфейс, чтобы определить возможность, которую могут разделять несколько несвязанных классов; используйте абстрактный класс, чтобы делить общее состояние и код между тесно связанными подклассами.

Может ли интерфейс в Java иметь тела методов?

Да, начиная с Java 8. Методы интерфейса, помеченные default, предоставляют тело, которое реализующие классы наследуют (и могут переопределять), а static-методы интерфейса предоставляют служебное поведение, вызываемое у самого интерфейса. Обычные методы интерфейса по-прежнему абстрактны -лишь сигнатура- и реализующие классы должны их определять.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ