java - 使用嵌套上限通配符时的不兼容类型

标签 java generics functional-programming bounded-wildcard

我正在开发 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> )。

所以,我有两个问题:

  1. 为什么会出现此错误?我预计会出现这种情况,其中 ? extends Type<? extends V>作品。在这种情况下我的期望是否被误用了?我可以看到我如何误读错误,因为涉及几种类型,而且我承认我不确定我的上述分析是否正确。
  2. 是否有对方法签名的修复,而不会牺牲灵活性,或者至少会牺牲灵活性?我希望这个库的用户不必担心由于我的 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 函数来解包 SupplierOption<? extends V>V引用,然后重新包装为 Option<V> .

关于java - 使用嵌套上限通配符时的不兼容类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61250994/

相关文章:

java - 点击按钮不起作用

java - 即使 .class 文件存在,也会出现 java.lang.NoClassDefFoundError 错误

java - Android studio,从插入类的类中继承变量

JavaFX TableView - 通用 OnEditCommit

c# - 如何为方法返回 double 或字符串

java - Java 8 中是否有用于参数检查的 requiredFalse 方法?

java - Android后台线程通信

java - 如何强制转换 List<T> 以便能够调用相应对象上的特定方法?

javascript - 如何使用 Ramda.js 重构这个组合函数?

lambda - 以标签作为参数的 F# 函数