В течение многих десятилетий это было так , что интерфейсы были только только (только) для определения сигнатуры методы. Нам сказали, что это был «правильный способ делать вещи».
Затем вышла Java 8 и сказала:
Ну, теперь вы можете определить методы по умолчанию. Должен бежать, пока.
Мне любопытно, как это усваивается как опытными разработчиками Java, так и теми, кто недавно (в последние несколько лет) начал его разработку. Мне также интересно, как это вписывается в ортодоксальность и практику Java.
Я создаю некоторый экспериментальный код, и в то время как я делал некоторый рефакторинг, я получил интерфейс, который просто расширяет стандартный интерфейс (Iterable) и добавляет два метода по умолчанию. И я буду честен, мне чертовски хорошо от этого.
Я знаю, что это немного открытый, но теперь, когда Java 8 уже использовалось в реальных проектах, есть ли ортодоксальность в использовании методов по умолчанию? Когда я обсуждаю их, я чаще всего вижу, как добавлять новые методы в интерфейс, не нарушая существующих потребителей. Но как насчет использования этого с самого начала, как в примере, который я привел выше. Кто-нибудь сталкивался с какими-либо проблемами с предоставлением реализаций в их интерфейсах?
источник
java.util.function.Function
с использованием методов по умолчанию в новом интерфейсе.Ответы:
Отличным вариантом использования являются то, что я называю «рычажными» интерфейсами: интерфейсы, которые имеют только небольшое количество абстрактных методов (в идеале 1), но предоставляют много «рычагов» в том, что они предоставляют вам множество функций: вы только Нужно реализовать 1 метод в вашем классе, но получить много других методов "бесплатно". Подумайте интерфейс сбора, например, с помощью одного абстрактного
foreach
метода иdefault
методов , такие какmap
,fold
,reduce
,filter
,partition
,groupBy
,sort
,sortBy
и т.д.Вот пара примеров. Давайте начнем с
java.util.function.Function<T, R>
. У него есть один абстрактный методR apply<T>
. И у него есть два метода по умолчанию, которые позволяют вам составлять функцию с другой функцией двумя различными способами, до или после. Оба эти метода компоновки реализованы с использованием толькоapply
:Вы также можете создать интерфейс для сопоставимых объектов, примерно так:
Или чрезвычайно упрощенный каркас коллекций, куда возвращаются все операции с коллекциями
Collection
, независимо от того, каким был исходный тип:Это становится очень интересным в сочетании с лямбдами, потому что такой «рычажный» интерфейс может быть реализован с помощью лямбды (это интерфейс SAM).
Это тот же вариант использования, для которого в C♯ были добавлены методы расширения, но методы по умолчанию имеют одно явное преимущество: они являются «правильными» методами экземпляра, что означает, что у них есть доступ к частным деталям реализации интерфейса (
private
методы интерфейса приходят в Java 9), тогда как методы расширения являются только синтаксическим сахаром для статических методов.Если бы Java когда-либо получала интерфейсную инъекцию, она также позволила бы модульное исправление обезьян, безопасное для типов. Это было бы очень интересно для языковых разработчиков на JVM: на данный момент, например, JRuby либо наследует, либо переносит классы Java, чтобы предоставить им дополнительную семантику Ruby, но в идеале они хотят использовать те же классы. С помощью метода «Внедрение интерфейса» и «Методы по умолчанию» они могут внедрять, например,
RubyObject
интерфейсjava.lang.Object
, так что JavaObject
и RubyObject
- это одно и то же .источник
Comparable
интерфейсе с абстрактнымcompareTo
способом, и по умолчаниюlessThan
,lessThanOrEqual
,greaterThan
,greaterThanOrEqual
,isBetween
, иclamp
методы, все реализованы в терминахcompareTo
. Или просто посмотритеjava.util.function.Function
: у него есть абстрактныйapply
метод и два метода композиции по умолчанию, оба реализованы в терминахapply
. Я попытался привести примерCollection
интерфейса, но сделать все это безопасным для типов сложно и слишком долго для этого ответа - я попытаюсь дать вариант, не безопасный для типов и сохраняющий тип. Будьте на связи.