Java 8 методы по умолчанию как черты: безопасный?
- это безопасная практика, чтобы использовать методы по умолчанию, как бедный человек, черт в Java 8?
некоторые утверждают, что это может сделать панды грустно если вы используете их только ради этого, потому что это круто, но это не входило в мои намерения. Также часто напоминается, что методы по умолчанию были введены для поддержки эволюции API и обратной совместимости, что верно, но это не делает его неправильным или искаженным, чтобы использовать их как черты как таковые.
I есть следующий практический случай использования внимание:
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 vs Scala черты; это не имеет значения здесь. Я тоже не просто спрашиваю мнения. Вместо этого я ищу авторитетный ответ или, по крайней мере, понимание поля: если вы использовали методы по умолчанию в качестве черт в своем корпоративном проекте, оказалось ли это бомбой замедленного действия?
1 ответ:
короткий ответ: это безопасно, если вы используете их спокойно :)
язвительный ответ: скажи мне, что вы имею в виду черты, и, возможно, я дам вам лучший ответ:)
на полном серьезе, термин "черта" не определяются. Многие разработчики Java наиболее знакомы с чертами, как они выражены в Scala, но Scala далеко не первый язык, чтобы иметь черты, либо по имени, либо по сути.
например, в Scala, черты являются статусными (может иметь
varпеременные); в крепости они являются чистым поведением. Интерфейсы Java с методами по умолчанию не имеют состояния; означает ли это, что они не являются чертами? (Подсказка: это был вопрос с подвохом.)опять же, в Scala черты составляются путем линеаризации; если класс
Aрасширяет чертыXиY, то порядок, в которомXиYсмешиваются в определяет, как конфликты междуXиYрешаются. В Java, это механизм линеаризации отсутствует (он был отклонен, отчасти, потому что он был слишком "не похож на Java".)непосредственной причиной добавления методов по умолчанию в интерфейсы была поддержка эволюция интерфейса, но мы прекрасно понимали, что едем дальше. Считаете ли вы, что это "эволюция интерфейса++" или "черты ..." - это вопрос личной интерпретации. Итак, чтобы ответить на ваш вопрос о безопасности ... пока вы придерживаетесь того, что механизм на самом деле поддерживает, а не пытается желая растянуть его на то, что он не поддерживает, Вы должны быть в порядке.
ключевой целью дизайна было то, что, с точки зрения клиент интерфейса, методы по умолчанию должны быть неотличимы от "обычных" методов интерфейса. Таким образом, по умолчанию метод интересен только для дизайнер и конструктор интерфейса.
вот некоторые использовать случаи, которые хорошо вписываются в цели дизайна:
эволюция интерфейса. Здесь мы добавляем новый метод к существующему интерфейсу, который имеет разумную реализацию по умолчанию с точки зрения существующих методов на этом интерфейсе. Примером может быть добавление
forEachметодCollection, где реализация по умолчанию записывается в терминахiterator()метод."дополнительно" методами. Здесь, дизайнер интерфейса говорит "Разработчики не должны реализовывать этот метод, если они готовы жить с ограничениями в функциональности, что влечет за собой". Например,
Iterator.removeбыл задан по умолчанию, который бросаетUnsupportedOperationException; так как подавляющее большинство реализацийIteratorв любом случае это поведение по умолчанию делает этот метод, по сути, необязательно. (Если поведение отAbstractCollectionбыли выражены как значения по умолчанию наCollection, мы могли бы сделать то же самое для методов мутационной.)методы удобства. Это методы, которые строго для удобства, опять же обычно реализуются в терминах нестандартных методов в классе. Элемент
logger()метод в вашем первом примере является разумной иллюстрацией этого.комбинаторы. Это композиционные методы, которые создают новые экземпляры интерфейса на основе текущего экземпляра. Например, методы
Predicate.and()илиComparator.thenComparing()примеры комбинаторы.если вы предоставляете реализацию по умолчанию, вы также должны предоставить некоторую спецификацию для значения по умолчанию (в JDK мы используем
@implSpecтег javadoc для этого), чтобы помочь разработчикам понять, хотят ли они, чтобы переопределить метод или нет. Некоторые значения по умолчанию, такие как методы удобства и комбинаторы, почти никогда не переопределяются; другие, такие как дополнительные методы, часто переопределяются. Вам нужно предоставить достаточную спецификацию (не только документация) о том, что обещает сделать по умолчанию, поэтому разработчик может принять разумное решение о том, нужно ли его переопределять.
Comments