Получить доступ

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

Контракт против частичной реализации, default/static/private-методы, разрешение конфликта default-методов и критерий выбора.

Контракт против частичной реализации

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

Ключевое структурное различие: класс реализует сколько угодно интерфейсов (множественное наследование типа), но наследует только один класс (одиночное наследование реализации). Поэтому интерфейсы — про «способности» из разных осей, а абстрактный класс — про общую основу одной иерархии.

default-методы

default-метод — метод с реализацией прямо в интерфейсе. Его ввели в Java 8, чтобы добавлять методы в существующие интерфейсы, не ломая всех, кто их уже реализует: классический пример — Collection.stream() и Iterable.forEach, которые «приехали» в старые интерфейсы как default.

Реализация по умолчанию наследуется автоматически и может быть переопределена. Это эволюция API, а не способ протащить состояние — состояния в интерфейсе по-прежнему нет.

static и private методы интерфейсов

Интерфейсы умеют и static-методы — обычно это фабрики и утилиты, логически связанные с типом: List.of(...), Comparator.comparing(...). Они вызываются по имени интерфейса и не наследуются реализациями.

С Java 9 в интерфейсах есть и private-методы — они не часть публичного контракта, а способ вынести общий код нескольких default-методов без дублирования.

Конфликт default-методов (diamond)

Если класс получает default-метод с одной сигнатурой из двух интерфейсов, компилятор не выбирает сам — это ошибка компиляции, и класс ОБЯЗАН переопределить метод, явно указав нужную версию через Interface.super.method().

Правила разрешения, когда конфликт неоднозначен лишь частично: класс важнее интерфейса (метод суперкласса побеждает default интерфейса), а более конкретный (под-) интерфейс важнее более общего.

interface A { default String hi() { return "A"; } }
interface B { default String hi() { return "B"; } }
class C implements A, B {
    public String hi() { return A.super.hi(); } // обязаны выбрать явно
}

Что выбирать

Интерфейс — когда тип выражает способность, реализации не связаны общей основой, или нужно «множественное наследование» поведения (Comparable, AutoCloseable, Runnable). Абстрактный класс — когда есть общее состояние и реализация, разделяемые тесной иерархией «является».

Современная рекомендация — предпочитать интерфейсы и композицию наследованию: интерфейс с default-методами часто заменяет абстрактный класс, не занимая единственный слот наследования и не навязывая состояние.

Как отвечать на собеседовании

Сформулируйте интерфейс=контракт без состояния (много на класс) против абстрактного класса=частичная реализация с состоянием (один). Объясните мотив default-методов (эволюция API: Collection.stream), static/private в интерфейсах, разрешение конфликта default через Interface.super и правило «класс > интерфейс». Завершите критерием выбора (способность/несвязанные типы → интерфейс; общая основа → абстрактный) и креном в сторону интерфейсов+композиции.

Вопросы по теме

Читайте также

Закрытая бета

Знать тему — половина дела

На живом собеседовании sotto слышит вопрос интервьюера и показывает короткий ответ и план. Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем