Интерфейс с методами по умолчанию vs Абстрактный class в Java 8

Поскольку Java 8 допускает стандартную реализацию методов в интерфейсе, называемом методами по умолчанию , кажется, существует путаница между тем, когда я буду использовать abstract class .

Итак, когда следует использовать интерфейс с методами по умолчанию и когда должен использоваться абстрактный class? Являются ли абстрактные classы еще полезными в этом сценарии?

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

Ограничением по умолчанию является то, что он может быть реализован только в терминах вызовов другим методам интерфейса без ссылки на состояние конкретной реализации. Таким образом, основной вариант использования – методы более высокого уровня и удобства.

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

Есть несколько технических отличий. Абстрактные classы могут по-прежнему делать больше по сравнению с интерфейсами Java 8:

  1. Абстрактный class может иметь конструктор.
  2. Абстрактные classы более структурированы и могут содержать состояние.

Концептуально основной целью методов защиты является обратная совместимость после внедрения новых функций (в виде lambda-функций) в Java 8.

Это описано в этой статье . Подумайте о forEach из собраний.

 List list = … list.forEach(…); 

Функция forEach не объявляется java.util.List или интерфейсом java.util.Collection . Одним из очевидных решений было бы просто добавить новый метод к существующему интерфейсу и обеспечить реализацию там, где это требуется в JDK. Однако после опубликования невозможно добавить методы к интерфейсу без нарушения существующей реализации.

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

Эти два совершенно разные:

Способы по умолчанию include добавление внешних функций к существующим classам без изменения их состояния.

И абстрактные classы являются обычным типом наследования, они являются нормальными classами, которые предназначены для расширения.

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

  1. Методы по умолчанию положили конец classическому шаблону интерфейса и сопутствующему classу, который реализует большинство или все методы в этом интерфейсе. Пример: Collection and AbstractCollection . Теперь мы должны реализовать методы в самом интерфейсе, чтобы обеспечить функциональность по умолчанию. Классы, реализующие интерфейс, имеют возможность переопределить методы или наследовать реализацию по умолчанию.
  2. Другим важным использованием методов по умолчанию является interface evolution . Предположим, у меня был class Ball as:

    public class Ball implements Collection { ... }

Теперь в Java 8 появились новые streamи функций. Мы можем получить stream, используя метод stream добавленный в интерфейс. Если stream не был методом по умолчанию, все реализации интерфейса Collection бы сломались, поскольку они не будут реализовывать этот новый метод. Добавление метода не по умолчанию к интерфейсу не source-compatible .

Но предположим, что мы не перекомпилируем class и не используем старый файл jar, который содержит этот class Ball . Класс будет загружаться без этого отсутствующего метода, экземпляры могут быть созданы, и кажется, что все работает нормально. НО, если программа вызывает метод stream на примере Ball мы получим AbstractMethodError . Поэтому решение по умолчанию решило обе проблемы.

По вашему запросу

Итак, когда следует использовать интерфейс с методами по умолчанию и когда должен использоваться абстрактный class? Являются ли абстрактные classы еще полезными в этом сценарии?

Java- документация обеспечивает идеальный ответ.

Абстрактные classы по сравнению с интерфейсами:

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

Однако с абстрактными classами вы можете объявлять поля, которые не являются статическими и окончательными, а также определять публичные, защищенные и частные конкретные методы.

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

Варианты использования для каждого из них были объяснены ниже в сообщении SE:

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

Являются ли абстрактные classы еще полезными в этом сценарии?

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

Как описано в этой статье,

Абстрактные classы и интерфейсы в Java 8

После введения метода по умолчанию кажется, что интерфейсы и абстрактные classы одинаковы. Тем не менее, они по-прежнему отличаются от концепции Java 8.

Абстрактный class может определять конструктор. Они более структурированы и могут иметь состояние, связанное с ними. Хотя, наоборот, метод по умолчанию может быть реализован только в терминах вызова других методов интерфейса без ссылки на состояние конкретной реализации. Следовательно, оба используются для разных целей, и выбор между двумя действительно зависит от контекста сценария.

Методы по умолчанию в интерфейсе Java позволяют развивать интерфейс .

Учитывая существующий интерфейс, если вы хотите добавить к нему метод, не нарушая бинарную совместимость со старыми версиями интерфейса, у вас есть два варианта: добавьте стандартный или статический метод. Действительно, любой абстрактный метод, добавленный в интерфейс, должен быть реализован classами или интерфейсами, реализующими этот интерфейс.

Статический метод уникален для classа. Метод по умолчанию уникален для экземпляра classа.

Если вы добавите метод по умолчанию к существующему интерфейсу, classы и интерфейсы, которые реализуют этот интерфейс, не нуждаются в его реализации. Они могут

  • реализовать метод по умолчанию, и он переопределяет реализацию в реализованном интерфейсе.
  • повторно объявить метод (без реализации), который делает его абстрактным.
  • ничего не делать (тогда метод по умолчанию из реализованного интерфейса просто наследуется).

Подробнее о теме здесь .

Почему мы должны использовать абстрактный class:

  1. Абстрактный class может иметь абстрактные и не абстрактные методы.
  2. Абстрактный class не поддерживает множественное наследование.
  3. Абстрактный class может иметь конечные, не конечные, статические и нестатические переменные.
  4. Абстрактный class может иметь статические методы, основной метод и конструктор.
  5. Абстрактный class может обеспечить реализацию интерфейса.
  6. Ключевое слово abstract используется для объявления абстрактного classа.

Почему мы должны использовать интерфейс:

  1. Интерфейс – это самый абстрактный уровень вашего приложения.
  2. Интерфейс поддерживает множественное наследование.
  3. Интерфейс, созданный только для описания сигнатур для подclass
  4. Интерфейс имеет только статические и конечные переменные.
  5. Используйте метод по умолчанию только для расширения некоторых интерфейсов, например внешней библиотеки. Но в основном это не хорошая практика 🙂

Правило Реми Форакс : вы не разрабатываете абстрактные classы. Вы разрабатываете приложение с помощью интерфейсов . Независимо от того, является ли версия Java, каков бы ни был язык. Это подтверждается принципом сегрегации I nterface в принципах SOL I D.

Вы можете использовать абстрактные classы для факторизации кода. Теперь с Java 8 вы можете сделать это прямо в интерфейсе. Это средство, а не больше.

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

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

Факты и ограничения:

1-May только объявляется внутри интерфейса, а не внутри classа или абстрактного classа.

2 – должен обеспечить тело

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

Методы по умолчанию в интерфейсе Java должны использоваться больше для обеспечения фиктивной реализации функции, тем самым сохраняя любой реализующий class этого интерфейса из-за боли при объявлении всех абстрактных методов, даже если они хотят иметь дело только с одним. Таким образом, методы по умолчанию в интерфейсе являются скорее заменой концепции classов адаптеров.

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

@ narendra-pathai: Пожалуйста, сначала подумайте о принципе открытия / закрытия. Методы по умолчанию в интерфейсах DO VIOLATE. Это плохая функция Java. Это поощряет плохой дизайн, плохую архитектуру, низкое качество программного обеспечения. Я предлагаю не использовать методы по умолчанию полностью.

Задайте себе несколько вопросов: – Почему вы не можете поместить свои методы в абстрактный class? Вам понадобится более одного абстрактного classа? Тогда подумайте о том, за что отвечает ваш class. Вы уверены, что все методы, которые вы собираетесь применить к одному classу, действительно выполняют ту же цель? Возможно, вы выделите несколько целей и затем разделите свой class на несколько classов, для каждой цели – свой class.

  • Таблицы стилей CSS по умолчанию для браузеров
  • Переадресация по умолчанию для Error 404
  • Существует ли разумный подход к параметрам типа «по умолчанию» в C # Generics?
  • Значение по умолчанию для типа в Runtime
  • Почему «final» не допускается в методах интерфейса Java 8?
  • Почему компилятор не может вывести тип шаблона из аргументов по умолчанию?
  • Как загрузить пакеты в R автоматически?
  • Объявление примитивов / объектов, значения инициализации по умолчанию
  • Создание (и доступ) разреженной матрицы с записями NA по умолчанию
  • Принудительный клиент telnet в режиме символов
  • Конструкторы и наследование по умолчанию в Java
  • Давайте будем гением компьютера.