Методы Java 8 по умолчанию как черты: безопасно?

Безопасно ли использовать методы по умолчанию в качестве черты характера плохого человека в Java 8?

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

У меня есть следующий пример практического использования в виду:

public interface Loggable {
    default Logger logger() {
        return LoggerFactory.getLogger(this.getClass());
    }
}

Или, возможно, определите PeriodTrait:

public interface PeriodeTrait {
    Date getStartDate();
    Date getEndDate();
    default isValid(Date atDate) {
        ...
    }
}

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

Итак, нормально ли /безопасно ли использовать методы по умолчанию в качестве основных характеристик , или мне следует беспокоиться о непредвиденных побочных эффектах?

Несколько вопросов о SO связаны с чертами Java и Scala; дело не в этом. Я не просто спрашиваю мнения. Вместо этого я ищу авторитетный ответ или, по крайней мере, полевую информацию: если вы использовали методы по умолчанию в качестве черт в своем корпоративном проекте, это оказалось бомбой замедленного действия?

108 голосов | спросил youri 23 FebruaryEurope/MoscowbMon, 23 Feb 2015 22:25:36 +0300000000pmMon, 23 Feb 2015 22:25:36 +030015 2015, 22:25:36

1 ответ


0

Короткий ответ: это безопасно, если вы используете их безопасно :)

Язвительный ответ: скажите мне, что вы подразумеваете под чертами, и, возможно, я дам вам лучший ответ :)

На самом деле, термин «черта» не является четко определенным. Многие Java-разработчики наиболее знакомы с чертами, поскольку они выражены в Scala, но Scala далека от первого языка, который имеет черты, либо по названию, либо по действию.

Например, в Scala признаки имеют состояние (могут иметь переменные var); в крепости они ведут себя чисто. Интерфейсы Java с методами по умолчанию не сохраняют состояния; это значит, что они не черты? (Подсказка: это был вопрос с подвохом.)

Опять же, в Scala черты формируются посредством линеаризации; если класс A расширяет черты X и ---- +: = 3 =: + ----, затем порядок, в котором Y и X в зависимости от того, как конфликтуют между Y и X разрешены. В Java этот механизм линеаризации отсутствует (он был частично отклонен, потому что он был слишком «не похож на Java»).

Непосредственной причиной добавления методов по умолчанию к интерфейсам была поддержка эволюции интерфейса , но мы хорошо понимали, что идем дальше. Считаете ли вы, что это «эволюция интерфейса ++» или «черты» - это вопрос личной интерпретации. Итак, чтобы ответить на ваш вопрос о безопасности ... пока вы придерживаетесь того, что механизм на самом деле поддерживает, а не пытаетесь по желанию растянуть его на то, что он не поддерживает, у вас все будет в порядке.

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

Вот несколько вариантов использования, которые хорошо соответствуют целям проекта:

  • Эволюция интерфейса. Здесь мы добавляем новый метод в существующий интерфейс, который имеет разумную реализацию по умолчанию с точки зрения существующих методов в этом интерфейсе. В качестве примера можно добавить метод Y к forEach, где реализация по умолчанию написана в терминах метода Collection.

  • «Необязательные» методы. Здесь разработчик интерфейса говорит: «Разработчикам не нужно реализовывать этот метод, если они хотят жить с ограничениями в функциональности, которые влекут за собой». Например, iterator() было задано значение по умолчанию, которое выдает Iterator.remove

  • Удобные методы. Это методы, которые предназначены исключительно для удобства, и, как правило, обычно реализуются с помощью методов, отличных от заданных по умолчанию. Метод Collection в вашем первом примере является разумной иллюстрацией этого.

  • Комбинаторы. Это композиционные методы, которые создают новые экземпляры интерфейса на основе текущего экземпляра. Например, методы logger() или Predicate.and() примеры комбинаторов.

Если вы предоставляете реализацию по умолчанию, вы должны также предоставить некоторую спецификацию для по умолчанию (в JDK мы используем javadoc Comparator.thenComparing() тег для этого), чтобы помочь разработчикам понять, хотят ли они переопределить метод или нет. Некоторые значения по умолчанию, такие как удобные методы и комбинаторы, почти никогда не отменяются; другие, как необязательнометоды, часто переопределяются. Вы должны предоставить достаточно спецификации (а не просто документацию) о том, что обещает сделать по умолчанию, чтобы разработчик мог принять разумное решение о том, нужно ли ему переопределять его.

ответил Brian Goetz 24 FebruaryEurope/MoscowbTue, 24 Feb 2015 01:38:19 +0300000000amTue, 24 Feb 2015 01:38:19 +030015 2015, 01:38:19

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132