Подтвердить что ты не робот

Java 8: методы виртуального расширения против абстрактного класса

Я рассматриваю новые методы виртуального расширения в интерфейсах Java 8:

public interface MyInterface {
   default String myMethod() { 
      return "myImplementation"; 
   }
}

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

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

4b9b3361

Ответ 1

Одной из основных целей таких конструкций является сохранение обратной совместимости. Добавление замыканий на язык Java является довольно существенным изменением, и все должно быть обновлено, чтобы полностью воспользоваться этим. Например, Collection в Java 8 будут иметь такие методы, как forEach(), которые работают вместе с lambdas. Простое добавление таких методов к ранее существующему интерфейсу Collection было бы невозможным, так как оно нарушило бы обратную совместимость. Класс, который я написал в Java 7, реализующий Collection больше не компилируется, так как ему не хватало этих методов. Следовательно, эти методы вводятся с реализацией по умолчанию. Если вы знаете Scala, вы можете видеть, что Java interface больше похожа на Scala trait s.

Что касается интерфейсов против абстрактных классов, то они все еще различаются в Java 8; например, вы по-прежнему не можете иметь конструктор в интерфейсе. Следовательно, оба подхода не являются "концептуально эквивалентными" как таковые. Абстрактные классы более структурированы и могут иметь связанное с ними состояние, тогда как интерфейсы не могут. Вы должны использовать то, что имеет смысл в контексте вашей программы, как и в Java 7 и ниже.

Ответ 2

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

Если вы хотите написать API, который позволяет пользователю использовать лямбда-выражения, вы должны использовать интерфейсы.

Ответ 3

Абстрактные классы содержат состояние (поля экземпляра), чтобы обеспечить некоторое общее поведение (методы).
Обычно вы (никогда?) Не видите абстрактный класс без состояния.

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

Ответ 4

Абстрактные классы оценивает интерфейсы java-8 в нижележащих областях.

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

  • Mutable state может быть разделен/изменен с помощью дочерних классов, в отличие от интерфейса, который имеет только константы

  • Абстрактный класс может быть использован для реализации Template_method_pattern: он определяет программный скелет алгоритма в операции, отложить некоторые шаги к подклассам.
  • Абстрактный класс может быть использован для реализации Decorator_pattern: шаблон дизайна, который позволяет поведению быть добавленным к индивидуальному объект, статически или динамически, не влияя на поведение других объектов из того же класса.