Шаблон Optional
в Guava великолепен, так как он помогает устранить двусмысленность с нулевым значением. Метод transform
очень полезен для создания нулевых цепочек методов, когда первая часть цепочки может отсутствовать, но бесполезен, когда другие части цепочки отсутствуют.
Этот вопрос связан с Необязательный тип Guava, когда преобразование возвращает другой Необязательный, который задает по существу тот же вопрос, но для другого варианта использования, который, я думаю, может не быть предполагаемым использованием Optional
(обработка ошибок).
Рассмотрим метод Optional<Book> findBook(String id)
. findBook(id).transform(Book.getName)
работает как положено. Если книга не найдена, мы получаем Absent<String>
, если книга найдена, мы получаем Present<String>
.
В общем случае, когда промежуточные методы могут возвращать null
/absent()
, кажется, нет элегантного способа связать вызовы в цепочку. Например, предположим, что у Book
есть метод Optional<Publisher> getPublisher()
, и мы хотели бы получить все книги, опубликованные издателем книги. Казалось бы, естественный синтаксис findBook(id).transform(Book.getPublisher).transform(Publisher.getPublishedBooks)
, однако это не удастся, потому что вызов transform(Publisher.getPublishedBooks)
на самом деле вернет Optional<Optional<Publisher>>
.
Кажется вполне разумным иметь transform()
-подобный метод для Optional
, который принимал бы функцию, возвращающую Optional
. Он будет действовать точно так же, как текущая реализация, за исключением того, что он просто не будет заключать результат функции в необязательный. Реализация (для Present
) может выглядеть так:
public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) {
return function.apply(reference);
}
Реализация для Absent
не отличается от transform
:
public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) {
checkNotNull(function);
return Optional.absent();
}
Также было бы неплохо, если бы существовал способ обработки методов, которые возвращают null
, а не Optional
для работы с устаревшими объектами. Такой метод будет похож на transform
, но просто вызовет Optional.fromNullable
в результате функции.
Мне любопытно, сталкивался ли кто-нибудь еще с этой неприятностью и нашел ли хорошие обходные пути (которые не включают в себя написание собственного класса Optional
). Я также хотел бы услышать от команды Guava или указать на обсуждения, связанные с проблемой (я не нашел ничего в своем поиске).