我正在开发 functional programming library对于 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
:
Bad return type in method reference: cannot convert
Option<V>
to? extends Option<? extends V>
My understanding of wildcard captures那是Option<? extends V>
接受 Option<T>
类型的任何对象哪里<T extends V>
,这意味着 Option<V>
绝对是Option<? extends V>
。同样,I'd expect那一个? extends Option<? extends V>
类型参数将接受相同的东西(如上的 Option<T>
或 Option<V>
)。
所以,我有两个问题:
- 为什么会出现此错误?我预计会出现这种情况,其中
? extends Type<? extends V>
作品。在这种情况下我的期望是否被误用了?我可以看到我如何误读错误,因为涉及几种类型,而且我承认我不确定我的上述分析是否正确。 - 是否有对方法签名的修复,而不会牺牲灵活性,或者至少会牺牲灵活性?我希望这个库的用户不必担心由于我的 API 而导致实际兼容的值和函数引发类型错误。
注意
我并不是要求实现 orElse
避免这种类型错误;我已经有一个工具可以做到这一点,并且我不太关心我的实现是否使用了较小的解决方法。我主要担心的是,这个库的用户在实现自己的解决方案时可能会遇到此类问题,因此我想让这些方法在类型上尽可能灵活,这就是为什么我首先拥有所有这些通配符。
最佳答案
啊啊,嵌套通配符。
不要按照你的预期行事。快速搜索给出 Multiple wildcards on a generic methods makes Java compiler (and me!) very confused作为规范答案的候选者。
实际上,您正在尝试获取 supp.get()
返回的类型( Option<? extends V>
) 由 orElse
返回( Option<V>
),这没有发生。
大概是 Option
的接口(interface)仅使用 V
担任生产者角色,但无法用 Java 表达这一点。
一个简单的修复方法是将返回类型设为 Option<? extends V>
.
您可以通过替换matchThen
的第二个参数来保留更好的界面使用 lambda 函数来解包 Supplier
和 Option<? extends V>
直V
引用,然后重新包装为 Option<V>
.
关于java - 使用嵌套上限通配符时的不兼容类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61250994/