Зачем использовать интерфейсы вместо классов
Что проверяют
Понимаете ли вы, что интерфейс это контракт, а класс это реализация, и зачем коду зависеть от контракта. Интервьюер ждёт не список букв SOLID, а практические причины из Java и Spring. Следом обычно спрашивают про отличия от абстрактного класса и про то, всегда ли нужен интерфейс.
Как отвечать
Главные доводы:
- множественная реализация: класс в Java наследует только один класс, но реализует сколько угодно интерфейсов. Один объект может быть и
Comparable, иAutoCloseable, иSerializable; - зависимость от контракта:
List<String> list = new ArrayList<>()позволяет заменить реализацию, не трогая вызывающий код. То же в сервисах: зависимость отPaymentGateway, а не от конкретного клиента банка, и есть принцип инверсии зависимостей; - расширяемость: новую реализацию добавляют, не меняя старый код. На этом держатся стратегии, плагины,
Comparator; - лямбды: функциональный интерфейс с одним абстрактным методом (
Runnable,Function, свой с@FunctionalInterface) реализуется лямбдой, класс так не заменишь; - закрытые иерархии: с Java 17 есть
sealed interfaceсо спискомpermits, а с Java 21switchс сопоставлением по образцу проверяет такую иерархию на полноту.
Про абстрактный класс: у интерфейса нет состояния экземпляра и конструктора, зато с Java 8 есть default и static методы, с Java 9 приватные. Абстрактный класс нужен, когда у реализаций общее состояние и общий шаблон поведения.
Хорошо добавить трезвую оговорку: если реализация одна и второй не предвидится, интерфейс ради интерфейса только добавляет файл.
Где спотыкаются
Утверждают, что интерфейсы нужны ради моков. Mockito давно мокает обычные классы, а с пятой версии по умолчанию и final-классы, так что это не главный довод.
Говорят, что в интерфейсе не бывает кода. Это верно только до Java 8.
Заводят пару UserService и UserServiceImpl для каждого бина по привычке. Spring Boot по умолчанию проксирует классы через CGLIB, интерфейс для работы @Transactional не обязателен, и без второй реализации такая пара только удваивает навигацию по коду.