Java 8 допускает реализацию методов по умолчанию в интерфейсах, называемых Методами по умолчанию .
Я запутался между тем, когда я бы использовал этот вид interface default method
вместо abstract class
(с abstract method(s)
).
Так когда же следует использовать интерфейс с методами по умолчанию и когда следует использовать абстрактный класс (с абстрактным методом)? Являются ли абстрактные классы полезными в этом сценарии?
java
interface
java-8
abstract-class
default-method
Нарендра Патхай
источник
источник
Ответы:
Абстрагировать классы можно гораздо больше, чем реализации методов по умолчанию (например, закрытое состояние), но в Java 8, когда у вас есть выбор, вы должны использовать метод defender (aka.
default
) В интерфейсе.Ограничение метода по умолчанию заключается в том, что он может быть реализован только в терминах вызовов других методов интерфейса без ссылки на состояние конкретной реализации. Таким образом, основной вариант использования - это методы более высокого уровня и удобства.
Хорошая особенность этой новой функции заключается в том, что там, где раньше вы были вынуждены использовать абстрактный класс для удобных методов, ограничивая таким образом разработчик единым наследованием, теперь вы можете получить действительно чистый дизайн с простым интерфейсом и минимумом реализации. усилие, наложенное на программиста.
Первоначальной мотивацией для введения
default
методов в Java 8 было желание расширить интерфейсы Collections Framework с помощью лямбда-ориентированных методов, не нарушая каких-либо существующих реализаций. Хотя это больше относится к авторам публичных библиотек, эта функция может оказаться полезной и в вашем проекте. У вас есть одно централизованное место, где можно добавить новые удобства, и вам не нужно полагаться на то, как выглядит остальная часть иерархии типов.источник
Есть несколько технических отличий. Абстрактные классы все еще могут делать больше по сравнению с интерфейсами Java 8:
Концептуально, основным назначением методов защитника является обратная совместимость после введения новых функций (как лямбда-функций) в Java 8.
источник
public static final
поля интерфейса как «состояние». Этаstatic
часть означает, что вы вообще не связаны с конкретным экземпляром. Они присваиваются при создании экземпляра класса , который отличается от создания экземпляра .Это описано в этой статье . Подумайте о
forEach
коллекциях.источник
AbstractList::forEach
бросатьUnsupportedOperationException
.Эти два совершенно разные:
Методы по умолчанию - добавить внешнюю функциональность к существующим классам без изменения их состояния.
И абстрактные классы являются нормальным типом наследования, они являются обычными классами, которые предназначены для расширения.
источник
Как описано в этой статье,
Абстрактные классы против интерфейсов в Java 8
источник
Что касается вашего запроса
Java документация обеспечивает идеальный ответ.
Абстрактные классы по сравнению с интерфейсами:
Варианты использования для каждого из них были объяснены в посте SE ниже:
В чем разница между интерфейсом и абстрактным классом?
Да. Они все еще полезны. Они могут содержать нестатические, неконечные методы и атрибуты ( защищенные, частные в дополнение к общедоступным ), что невозможно даже с интерфейсами Java-8.
источник
Всякий раз, когда у нас есть выбор между абстрактным классом и интерфейсом, мы всегда (почти) предпочитаем методы по умолчанию (также известные как защитники или виртуальные расширения).
Collection and AbstractCollection
. Теперь мы должны реализовать методы в самом интерфейсе, чтобы обеспечить функциональность по умолчанию. Классы, которые реализуют интерфейс, могут переопределять методы или наследовать реализацию по умолчанию.Другое важное использование методов по умолчанию
interface evolution
. Предположим, у меня был класс Ball как:public class Ball implements Collection { ... }
Теперь в Java 8 появилась новая функция потоков. Мы можем получить поток, используя
stream
метод, добавленный в интерфейс. Если быstream
не было метода по умолчанию, все реализацииCollection
интерфейса были бы повреждены, поскольку они не реализовывали бы этот новый метод. Добавление метода не по умолчанию для интерфейса не являетсяsource-compatible
.Но предположим, что мы не перекомпилируем класс и используем старый файл jar, который содержит этот класс
Ball
. Класс будет нормально загружаться без этого отсутствующего метода, экземпляры могут быть созданы, и кажется, что все работает нормально. НО, если программа вызываетstream
метод по экземпляру,Ball
мы получимAbstractMethodError
. Таким образом, создание метода по умолчанию решило обе проблемы.источник
Методы по умолчанию в интерфейсе Java обеспечивают эволюцию интерфейса .
При наличии существующего интерфейса, если вы хотите добавить к нему метод, не нарушая бинарную совместимость со старыми версиями интерфейса, у вас есть два варианта: добавить метод по умолчанию или статический метод. Действительно, любой абстрактный метод, добавленный к интерфейсу, должен быть реализован классами или интерфейсами, реализующими этот интерфейс.
Статический метод уникален для класса. Метод по умолчанию уникален для экземпляра класса.
Если вы добавляете метод по умолчанию в существующий интерфейс, классы и интерфейсы, которые реализуют этот интерфейс, не нуждаются в его реализации. Они могут
Подробнее по теме здесь .
источник
Хотя это старый вопрос, позвольте мне также внести свой вклад в него.
абстрактный класс: внутри абстрактного класса мы можем объявить переменные экземпляра, которые требуются дочернему классу
Интерфейс: Внутри интерфейса каждая переменная всегда общедоступна, и, наконец, мы не можем объявить переменные экземпляра.
абстрактный класс: абстрактный класс может говорить о состоянии объекта
Интерфейс: Интерфейс никогда не может говорить о состоянии объекта
абстрактный класс: внутри абстрактного класса мы можем объявить конструкторы
Интерфейс: Внутри интерфейса мы не можем объявлять конструкторы, так как целью
конструкторов является инициализация переменных экземпляра. Так зачем же нужен конструктор, если у нас не может быть переменных экземпляра в интерфейсах ?
абстрактный класс: внутри абстрактного класса мы можем объявить экземпляры и статические блоки
Интерфейс: Интерфейсы не могут иметь экземпляров и статических блоков.
абстрактный класс: абстрактный класс не может ссылаться на лямбда-выражение
Интерфейсы: интерфейсы с одним абстрактным методом могут ссылаться на лямбда-выражения
абстрактный класс : внутри абстрактного класса мы можем переопределить методы OBJECT CLASS
Интерфейсы: Мы не можем переопределить методы OBJECT CLASS внутри интерфейсов.
Я закончу на примечании, что:
Концепции метода по умолчанию / статические методы метода в интерфейсе пришли просто для того, чтобы сохранить классы реализации, но не для обеспечения содержательной полезной реализации. Методы по умолчанию / статические методы являются своего рода фиктивной реализацией, «если вы хотите, вы можете использовать их или вы можете переопределить их (в случае методов по умолчанию) в классе реализации», тем самым избавляя нас от реализации новых методов в классах реализации всякий раз, когда новые методы в интерфейсах добавлены. Поэтому интерфейсы никогда не могут быть равны абстрактным классам.
источник
Правило Remi Forax : Вы не проектируете классы Abstract. Вы разрабатываете свое приложение с интерфейсами . Какой бы ни была версия Java, каким бы ни был язык. Она опирается на I принцип сегрегации nterface в SOL I D принципов.
Позже вы можете использовать абстрактные классы для факторизации кода. Теперь с Java 8 вы можете сделать это прямо в интерфейсе. Это средство, не более.
источник
Обратная совместимость: представьте себе, что ваш интерфейс реализован сотнями классов, изменение этого интерфейса заставит всех пользователей реализовать недавно добавленный метод, даже если это может быть несущественным для многих других классов, реализующих ваш интерфейс, плюс это позволяет вашему интерфейсу быть функциональным интерфейсом
Факты и ограничения:
1-может быть объявлено только внутри интерфейса, а не внутри класса или абстрактного класса.
2-должны обеспечить тело
3. Предполагается, что он не является абстрактным, как другие обычные методы, используемые в интерфейсе.
источник
В Java 8 интерфейс выглядит как абстрактный класс, хотя они могут иметь некоторые отличия, такие как:
1) Абстрактные классы являются классами, поэтому они не ограничены другими ограничениями интерфейса в Java, например, абстрактный класс может иметь состояние , но вы не можете иметь состояние интерфейса в Java.
2) Другое семантическое различие между интерфейсом с методами по умолчанию и абстрактным классом заключается в том, что вы можете определять конструкторы внутри абстрактного класса , но вы не можете определить конструктор внутри интерфейса в Java.
источник
Методы по умолчанию в Java Interface должны использоваться в большей степени для обеспечения фиктивной реализации функции, таким образом, сохраняя любой реализующий класс этого интерфейса от боли объявления всех абстрактных методов, даже если они хотят иметь дело только с одним. Методы по умолчанию в интерфейсе, таким образом, являются заменой концепции классов адаптеров.
Однако предполагается, что методы в абстрактном классе дают значимую реализацию, которую любой дочерний класс должен переопределять, только если это необходимо для переопределения общей функциональности.
источник
Как упоминалось в других ответах, была добавлена возможность добавлять реализацию к интерфейсу для обеспечения обратной совместимости в структуре коллекций. Я бы сказал, что обеспечение обратной совместимости является единственной хорошей причиной для добавления реализации в интерфейс.
Иначе, если вы добавите реализацию к интерфейсу, вы нарушите основной закон, почему интерфейсы были добавлены в первую очередь. Java - это язык с одним наследованием, в отличие от C ++, который допускает множественное наследование. Интерфейсы предоставляют преимущества типизации, которые поставляются с языком, который поддерживает множественное наследование, не создавая проблем, связанных с множественным наследованием.
В частности, Java допускает только одно наследование реализации, но допускает множественное наследование интерфейсов. Например, следующий допустимый код Java:
MyObject
наследует только одну реализацию, но наследует три контракта.Java передала множественное наследование реализации, потому что множественное наследование реализации сопровождается множеством острых проблем, которые выходят за рамки этого ответа. Интерфейсы были добавлены, чтобы разрешить множественное наследование контрактов (или интерфейсы) без проблем множественного наследования реализации.
Чтобы поддержать мою точку зрения, вот цитата Кена Арнольда и Джеймса Гослинга из книги «Язык программирования Java, 4-е издание» :
источник
Пожалуйста, подумайте сначала об открытом / закрытом принципе. Методы по умолчанию в интерфейсах нарушают его. Это плохая функция в Java. Это поощряет плохой дизайн, плохую архитектуру, низкое качество программного обеспечения. Я бы предложил полностью избегать использования методов по умолчанию.
Задайте себе несколько вопросов: почему вы не можете поместить свои методы в абстрактный класс? Вам понадобится более одного абстрактного класса? Затем подумайте, за что отвечает ваш класс. Вы уверены, что все методы, которые вы собираетесь использовать в одном классе, действительно выполняют одну и ту же цель? Может быть, вы будете различать несколько целей, а затем разделите свой класс на несколько классов, для каждой цели свой класс.
источник