Я работаю над библиотекой функционального программирования для Java и столкнулся с неприятной проблемой. В моем классе Option<V>
есть следующие функции:
/**
* Returns an Option containing the provided value.
*/
public static <V> Option<V> some(V value)
{...}
/**
* Returns an Option that contains nothing.
*/
public static <V> Option<V> none()
{...}
/**
* Decide control flow based on whether this is Some or None,
* returning the result of the chosen operation.
*
* @param some the operation to perform on the contained value if there is one
* @param none the operation to perform if there is no contained value
* @return the result of the matched operation
*/
public <T> T matchThen(Function<? super V, ? extends T> some, Supplier<? extends T> none)
{...}
В настоящее время я реализую метод orElse
, который использует методы, описанные выше, и реализован так:
/**
* Returns this if it is a Some, otherwise computes an Option from the given Supplier.
* @param supp the supplier to compute the other Option
* @return the first present value or None
*/
public Option<V> orElse(Supplier<? extends Option<? extends V>> supp)
{
return matchThen(
Option::some, // if there is a value, wrap it back up and return it
supp::get // if there isn't a value, get one from the supplier
);
}
IDEA сообщает об ошибке с использованием Option::some
в orElse
:
Неверный тип возврата в ссылке на метод: невозможно преобразовать Option<V>
в ? extends Option<? extends V>
Мое понимание подстановочных знаков заключалось в том, что Option<? extends V>
принимает любой объект типа Option<T>
, где <T extends V>
, что означало бы, что Option<V>
определенно является Option<? extends V>
. Аналогично, Я бы ожидал , что параметр типа ? extends Option<? extends V>
примет то же самое (Option<T>
, как указано выше или Option<V>
).
Итак, у меня есть два вопроса :
- Почему происходит эта ошибка? Я ожидал, что это будет случай , где
? extends Type<? extends V>
работает. В этом случае мои ожидания неверно применяются? Я вижу, как я мог неправильно истолковать ошибку, так как задействовано несколько типов, и я признаю, что не уверен, что мой приведенный выше анализ верен. - Есть ли исправление сигнатур методов, которое не жертвуете гибкостью или делает это минимально? Я бы хотел, чтобы пользователи этой библиотеки не беспокоились о реально совместимых значениях и функциях, вызывающих ошибки типов из-за моего API.
Примечание
Я не спрашиваю для реализации orElse
, которая избегает этой ошибки типа; У меня уже есть инструмент для этого, и мне все равно, использует ли моя реализация незначительные обходные пути. Мое главное беспокойство заключается в том, что пользователи этой библиотеки могут столкнуться с проблемой такого типа при реализации своих собственных решений, поэтому я хочу сделать эти методы максимально гибкими для типов, поэтому я в первую очередь использую все эти шаблоны.