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

В моем проекте используется определенная библиотека. Эта библиотека имеет интерфейс, который имеет около 15 методов.

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

Все методы в этом интерфейсе - это фактически события. Могут быть слушатели, которым требуется только одно или два события из многих событий в интерфейсе. Несмотря на то, что слушатель интересуется только несколькими событиями, слушатель должен реализовать все методы при расширении интерфейса.

Поэтому я попросил разработчика этой библиотеки добавить пустые реализации по умолчанию в методы в интерфейсе.

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

Но, как я понимаю, метод в этом интерфейсе не указывает какое-то действие, на которое должен быть способен реализатор этого интерфейса. Метод в этом интерфейсе скорее определяет событие, которое может заинтересовать разработчик. Поэтому я не вижу ясной причины не добавлять стандартные реализации.

Итак, добавляет ли реализация по умолчанию к этому интерфейсу нарушить лучшие практики java?

Ответ 1

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

Этот аргумент был действителен до тех пор, пока не будут введены методы интерфейса по умолчанию. Теперь вашему коллеге пришлось бы утверждать, что JLS Java 8 извращенных интерфейсов и JDK теперь содержат классы, которые противоречат назначению интерфейсов. Тем не менее это жизнеспособная крайняя точка зрения, но бесплодная.

Вы просто можете избежать обсуждения, выведя собственный интерфейс из интерфейса библиотеки и предоставляя стандартные пустые реализации для всех унаследованных методов.

public interface MyInterface extends LibraryInterface {
    @Override default public void event1() {
    }

    ...
}

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

Несмотря на то, что слушателя интересует только несколько событий, слушатель должен реализовать все методы при расширении интерфейса.

Решением может быть просто разделить большой интерфейс на многие более мелкие.

Ответ 2

Разработчик библиотеки ошибается в этом (я даже осмеливаюсь пропустить IMHO).

Одна из причин того, что многие вспомогательные (как абстрактные, так и конкретные) классы в Java были введены в прошлом, - это в точности отсутствие таких функций, как методы интерфейса по умолчанию (например, классы адаптеров в Swing, которые очень напоминают проблемы, которые вы испытываете спрашивают).

Если не использовать неправильно, в некоторых ситуациях желательно многократное наследование, и, как мы все знаем, расширяя класс "помощник" в Java, мы теряем способность наследовать что-либо еще.

Собственно, это упоминается в официальном учебнике Java, раздел "Абстрактные классы по сравнению с интерфейсами":

Рассмотрите возможность использования интерфейсов, если какое-либо из этих утверждений относится к вашему ситуация:

  • Вы ожидаете, что не связанные классы будут реализовывать ваш интерфейс. Например, реализованы интерфейсы Comparable и Cloneable многими несвязанными классами.
  • Вы хотите указать поведение конкретного типа данных, но не обеспокоены тем, кто реализует его поведение.
  • Вы хотите использовать множественное наследование типа.

Вторая и третья точки - идеальное совпадение для вашего случая использования, я думаю.

Ответ 3

Поскольку методы по умолчанию позволяют нам добавлять новые функциональные возможности в интерфейсы, не нарушая классы, реализующие этот интерфейс, поэтому он определенно не является хорошей практикой, потому что он сочетает в себе достоинства интерфейсов и абстрактных классов, но поскольку это не вариант, я бы настоятельно рекомендуем, чтобы вы предоставили свой собственный класс реализации скелета, поскольку эта "методология" используется во всей структуре коллекций в java, и это просто мое скромное мнение.