Интерфейс с методами по умолчанию vs Абстрактный класс в Java 8
Так как Java 8 допускает использование по умолчанию методов в интерфейсе Способы по умолчанию, похоже, возникает путаница между тем, когда я буду использовать abstract class
.
Итак, когда следует использовать интерфейс со стандартными методами и когда должен использоваться абстрактный класс? Являются ли абстрактные классы еще полезными в этом сценарии?
Ответы
Ответ 1
Абстрагировать классы можно гораздо больше, чем реализации методов по умолчанию (например, закрытое состояние), но, начиная с Java 8, всякий раз, когда у вас есть выбор, следует использовать метод defender (aka. default
) в интерфейсе.
Ограничение метода по умолчанию заключается в том, что он может быть реализован только в терминах вызовов других методов интерфейса без ссылки на конкретное состояние реализации. Таким образом, основной вариант использования - это методы более высокого уровня и удобства.
Хорошая особенность этой новой функции заключается в том, что там, где раньше вы были вынуждены использовать абстрактный класс для удобных методов, ограничивая таким образом разработчик единым наследованием, теперь вы можете получить действительно чистый дизайн с простым интерфейсом и минимумом реализации. усилие, наложенное на программиста.
Первоначальной мотивацией для введения методов default
в Java 8 было желание расширить интерфейсы Collections Framework с помощью лямбда-ориентированных методов, не нарушая каких-либо существующих реализаций. Хотя это больше относится к авторам публичных библиотек, эта функция может оказаться полезной и в вашем проекте. У вас есть одно централизованное место, где можно добавить новые удобства, и вам не нужно полагаться на то, как выглядит остальная часть иерархии типов.
Ответ 2
Есть несколько технических отличий. Абстрактные классы все еще могут делать больше по сравнению с интерфейсами Java 8:
- Абстрактный класс может иметь конструктор.
- Абстрактные классы более структурированы и могут содержать состояние.
Концептуально основная цель методов защиты - это обратная совместимость после внедрения новых функций (в виде лямбда-функций) в Java 8.
Ответ 3
Это описано в этой статье . Подумайте о forEach
коллекций.
List<?> list = …
list.forEach(…);
Объявление forEach не объявляется java.util.List
, а java.util.Collection
. Одним из очевидных решений было бы просто добавьте новый метод в существующий интерфейс и обеспечьте в случае необходимости в JDK. Однако после опубликования он невозможно добавить методы к интерфейсу, не нарушая существующая реализация.
Преимущество, которое применяют методы по умолчанию, заключается в том, что теперь его можно добавьте новый интерфейс по умолчанию к интерфейсу, и он не сломает реализации.
Ответ 4
Как описано в этой статье,
Абстрактные классы и интерфейсы в Java 8
После введения метода по умолчанию кажется, что интерфейсы и абстрактные классы одинаковы. Тем не менее, они по-прежнему разные концепции в Java 8.
Абстрактный класс может определять конструктор. Они более структурированы и может иметь состояние, связанное с ними. Хотя по умолчанию метод может быть реализован только с точки зрения привлечения других методы интерфейса, без ссылки на конкретную реализацию государство. Следовательно, оба используют для разных целей и выбирают между двумя действительно зависит от контекста сценария.
Ответ 5
Эти два совершенно разные:
Способы по умолчанию: добавить внешние функции к существующим классам без изменения их состояния.
И абстрактные классы являются обычным типом наследования, они нормальные классы, которые предназначены для расширения.
Ответ 6
Всякий раз, когда у нас есть выбор между абстрактным классом и интерфейсом, мы всегда (почти) предпочитаем методы по умолчанию (также известные как защитники или виртуальные расширения).
- По умолчанию методы положили конец классическому шаблону интерфейса и сопутствующему классу, который реализует большинство или все методы в этом интерфейсе. Пример:
Collection and AbstractCollection
. Теперь мы должны реализовать методы в самом интерфейсе, чтобы обеспечить функциональность по умолчанию. Классы, реализующие интерфейс, имеют возможность переопределить методы или наследовать реализацию по умолчанию.
-
Еще одно важное использование методов по умолчанию - interface evolution
. Предположим, что у меня был класс Ball as:
public class Ball implements Collection { ... }
Теперь в Java 8 появились новые потоки функций. Мы можем получить поток, используя метод stream
, добавленный в интерфейс. Если stream
не был методом по умолчанию, все реализации для интерфейса Collection
сломались бы, поскольку они не будут реализовывать этот новый метод. Добавление метода не по умолчанию к интерфейсу не source-compatible
.
Но предположим, что мы не перекомпилируем класс и не используем старый файл jar, который содержит этот класс Ball
. Класс будет загружаться без этого отсутствующего метода, экземпляры могут быть созданы, и кажется, что все работает нормально. НО, если программа вызывает метод stream
в экземпляре Ball
, мы получим AbstractMethodError
. Таким образом, метод по умолчанию решил обе проблемы.
Ответ 7
Что касается вашего запроса
Итак, когда следует использовать интерфейс со стандартными методами и когда должен использоваться абстрактный класс? Являются ли абстрактные классы еще полезными в этом сценарии?
java документация обеспечивает прекрасный ответ.
Абстрактные классы по сравнению с интерфейсами:
Абстрактные классы аналогичны интерфейсам. Вы не можете создавать их, и они могут содержать сочетание методов, объявленных с реализацией или без нее.
Однако, с абстрактными классами, вы можете объявлять поля, которые не являются статическими и окончательными, и определять публичные, защищенные и частные конкретные методы.
С интерфейсами все поля автоматически являются общедоступными, статическими и конечными, а все методы, которые вы объявляете или определяете (как методы по умолчанию), являются общедоступными. Кроме того, вы можете расширить только один класс, независимо от того, является он абстрактным, тогда как вы можете реализовать любое количество интерфейсов.
Примеры использования для каждого из них были объяснены ниже в сообщении SE:
В чем разница между интерфейсом и абстрактным классом?
Являются ли абстрактные классы еще полезными в этом сценарии?
Да. Они по-прежнему полезны. Они могут содержать нестатические, не конечные методы и атрибуты (защищенные, частные в дополнение к общедоступным), что невозможно даже при использовании интерфейсов Java-8.
Ответ 8
Методы по умолчанию в интерфейсе Java обеспечивают эволюцию интерфейса.
При наличии существующего интерфейса, если вы хотите добавить к нему метод, не нарушая бинарную совместимость со старыми версиями интерфейса, у вас есть два варианта: добавить метод по умолчанию или статический метод. Действительно, любой абстрактный метод, добавленный к интерфейсу, должен быть реализован классами или интерфейсами, реализующими этот интерфейс.
Статический метод уникален для класса. Метод по умолчанию уникален для экземпляра класса.
Если вы добавляете метод по умолчанию к существующему интерфейсу, классы и интерфейсы, которые реализуют этот интерфейс, не нуждаются в его реализации. Они могут
- реализовать метод по умолчанию, и он переопределяет реализацию в реализованном интерфейсе.
- повторно объявите метод (без реализации), что делает его абстрактным.
- ничего не делать (тогда метод по умолчанию из реализованного интерфейса просто наследуется).
Подробнее о теме здесь.
Ответ 9
Правило Remi Forax Вы не создаете абстрактные классы. Вы разрабатываете свое приложение с интерфейсами. Независимо от того, является ли версия Java, каков бы ни был язык. Это поддерживается принципом сегрегации I в Принципы SOL I D.
Вы можете использовать абстрактные классы для факторизации кода. Теперь с Java 8 вы можете сделать это прямо в интерфейсе. Это объект, не более.
Ответ 10
Почему мы должны использовать абстрактный класс:
- Абстрактный класс может иметь абстрактные и не абстрактные методы.
- Абстрактный класс не поддерживает множественное наследование.
- Абстрактный класс может иметь конечные, не конечные, статические и нестатические переменные.
- Абстрактный класс может иметь статические методы, основной метод и конструктор.
- Абстрактный класс может обеспечить реализацию интерфейса.
- Ключевое слово abstract используется для объявления абстрактного класса.
Почему мы должны использовать интерфейс:
- Интерфейс - это наиболее абстрактный уровень дизайна вашего приложения.
- Интерфейс поддерживает множественное наследование.
- Интерфейс, созданный только для описания сигнатур для подкласс
- Интерфейс имеет только статические и конечные переменные.
- Использовать метод по умолчанию только для расширения некоторых интерфейсов, например внешней библиотеки. Но в основном это не хорошая практика:)
Ответ 11
когда следует использовать интерфейс с методами по умолчанию, и когда абстрактный класс?
Обратная совместимость:
Представьте, что ваш интерфейс реализован сотнями классов, модифицируя этот интерфейс, чтобы заставить всех пользователей реализовать недавно добавленный метод, даже если это может быть не существенно для многих других классов, которые реализуют ваш интерфейс. Кроме того, это позволяет вашему интерфейсу быть функциональный интерфейс
Факты и ограничения:
1-May может быть объявлен только внутри интерфейса, а не внутри класса или
абстрактный класс.
2-Должен обеспечить тело
3. Это не считается абстрактным, как другие обычные методы, используемые в интерфейсе.
Ответ 12
В Java 8 интерфейс выглядит как абстрактный класс, хотя они могут иметь некоторые отличия, такие как:
1) Абстрактные классы являются классами, поэтому они не ограничены другими ограничениями интерфейса в Java, например абстрактный класс может иметь состояние, но вы не можете иметь состояние на интерфейсе в Java.
2) Другое семантическое отличие между интерфейсом с методами по умолчанию и абстрактным классом заключается в том, что вы можете определять конструкторы внутри абстрактного класса, но вы не можете определить конструктор внутри интерфейса в Java
Ответ 13
В Java 8
мы можем иметь конкретные методы в пределах interfaces
.. right.. Так как он отличается от классов Abstract
? Помните, что абстрактный класс - это класс, который не может быть создан (т.е. Объекты не могут быть созданы) и может содержать тела методов. Метод по умолчанию в Java 8 похож на абстрактный класс, не так ли?
Ну, на самом деле это разные. Абстрактный класс может содержать состояние объекта. Он может иметь конструкторы и переменные-члены. В то время как интерфейсы с методами Java 8 по умолчанию не могут содержать состояние. Он не может иметь конструкторов и переменных-членов. Вы все равно должны использовать абстрактный класс всякий раз, когда думаете, что ваш класс может иметь состояние или вам нужно что-то сделать в конструкторе. Метод по умолчанию должен использоваться для обратной совместимости. Всякий раз, когда вы хотите добавить дополнительные функциональные возможности в существующий унаследованный интерфейс, вы можете использовать методы по умолчанию, не нарушая существующие классы реализации
Ответ 14
@Masudul: вы повторяете ложные утверждения. "и он не нарушает реализации" - это неправильно. Например, попробуйте добавить метод к интерфейсу, который уже реализован в некоторых классах, но с другим типом возврата. Конечно, это реализация WILL BREAK.
Ответ 15
Способы по умолчанию в Java-интерфейсе должны использоваться больше для предоставления фиктивной реализации функции, тем самым сохраняя любой реализующий класс этого интерфейса от боли при объявлении всех абстрактных методов, даже если они хотят иметь дело только с одним.
Таким образом, методы по умолчанию в интерфейсе являются скорее заменой концепции классов адаптеров.
Однако методы в абстрактном классе должны давать значимую реализацию, которую любой дочерний класс должен переопределять, только если необходимо переопределить общую функциональность.
Ответ 16
Как упоминалось в других ответах, была добавлена возможность добавлять реализацию к интерфейсу для обеспечения обратной совместимости в структуре коллекций. Я бы сказал, что обеспечение обратной совместимости является единственной хорошей причиной для добавления реализации в интерфейс.
В противном случае, если вы добавите реализацию к интерфейсу, вы нарушите основной закон, почему интерфейсы были добавлены в первую очередь. Java - это язык с одним наследованием, в отличие от C++, который допускает множественное наследование. Интерфейсы обеспечивают преимущества при наборе текста, которые поставляются с языком, который поддерживает множественное наследование, не создавая проблем, связанных с множественным наследованием.
В частности, Java допускает только одно наследование реализации, но допускает множественное наследование интерфейсов. Например, следующий допустимый код Java:
class MyObject extends String implements Runnable, Comparable { ... }
MyObject
наследует только одну реализацию, но наследует три контракта.
Java передала множественное наследование реализации, потому что множественное наследование реализации сопровождается множеством острых проблем, которые выходят за рамки этого ответа. Интерфейсы были добавлены, чтобы разрешить множественное наследование контрактов (или интерфейсы) без проблем множественного наследования реализации.
Чтобы поддержать мою точку зрения, вот цитата Кена Арнольда и Джеймса Гослинга из книги "Язык программирования Java, 4-е издание":
Одиночное наследование исключает некоторые полезные и правильные конструкции. проблемы множественного наследования возникают из множественного наследования реализации, но во многих случаях множественное наследование используется для наследовать ряд абстрактных контрактов и, возможно, один конкретный реализация. Предоставление средств для наследования абстрактного контракта без наследования реализации позволяет печатать преимущества множественное наследование без проблем множественной реализации наследование. Наследование абстрактного договора называется наследование интерфейса. Язык программирования Java поддерживает наследование интерфейса, позволяя вам объявить тип interface
Ответ 17
Пожалуйста, подумайте сначала об открытом/закрытом принципе. Методы по умолчанию в интерфейсах нарушают его. Это плохая функция в Java. Это поощряет плохой дизайн, плохую архитектуру, низкое качество программного обеспечения. Я бы предложил полностью избегать использования методов по умолчанию.
Задайте себе несколько вопросов:
Почему вы не можете поместить свои методы в абстрактный класс? Вам понадобится более одного абстрактного класса? Затем подумайте, за что отвечает ваш класс. Вы уверены, что все методы, которые вы собираетесь использовать в одном классе, действительно выполняют одну и ту же цель? Может быть, вы будете различать несколько целей, а затем разделите свой класс на несколько классов, для каждой цели свой класс.