给定 `T` 和 `U`,其中 `T extends U` 如何 return 一个 `U`

Given `T` and `U` where `T extends U` how to return a `U`

给定一个 API 喜欢:

class Bar { ... }
class Foo extends Bar { ... }

在Java的Optional类型中,我们可以说:

Optional<Foo> fooOption = ...
fooOption.orElse(aFoo) // returns something of type Foo

但是,由于 FooBar,我想说:

Optional<Foo> fooOption = ...
fooOption.orElse(aBar) // returns something of type Bar

作为练习,我想用另一种类型来完成这个:

public abstract class Option<T> {
    // this doesn't compile
    public abstract <U super T> U orElse(U other);
}

我如何重写它来编译,同时支持在需要时扩大类型的能力?

But, since Foo is a Bar

但是 Bar 不是 Foo。我的意思是你可以这样做:

Optional<Bar> fooOpt = Optional.of(new Foo());
Bar bar = fooOpt.orElse(new Bar());

但是你不能用 Optional<Foo> 做同样的事情,因为它违反了 Optional.orElse 方法的类型限制。

Option<T> 的假设实现中,您应该将 U 明确定义为 T

的超类型
public class Option<U, T extends U> {
    T value;

    public U orElse(U other) {
        if (value != null) {
            return value;
        }
        return other;
    }
}

在那种情况下你可以写这样的代码

Option<Foo, Bar> fooOpt = Option.of(new Foo());
Bar bar = fooOpt.orElse(new Bar());

因为 U 应该是 T 的超类型,你可以这样做:

public abstract class Option<U, T extends U> {

    public abstract of(T value);

    public abstract U orElse(U other);

}

您的问题中有一个基本前提存在缺陷:

In Java's Optional type, we can say:

Optional fooOption = ... fooOption.orElse(aFoo) // returns something of type Foo But, since Foo is a Bar, I would like to be able to say:

Optional fooOption = ... fooOption.orElse(aBar) // returns something of type Bar

Foo 是 Bar,但 Bar 不是 Foo。如果您的通用定义如下:

Optional<Foo> fooOption = ...

然后你可以return任何Foo类型的东西。 Bar 不是 类型 Foo.

如果你有一个额外的对象:

class FooBar extends Foo{}

然后你可以在你的例子中将它转换为 foo:

Optional fooOption = ...

fooOption.orElse(aFooBar) // returns something of type Foo

或者,如果您已将 Optional 定义为 Optional<Bar>,那么您可以使用 FooBarFooBar 对象,因为它们都是类型 Bar.

或继承自类型 Bar.

关于你问题的第二部分:

public abstract class Option<T> {
    // this doesn't compile
    public abstract <U super T> U orElse(U other);
}
 

只需使用通用超类型编写即可:

public abstract class Option<T> {
    // this now compiles.
    public abstract T orElse(T other);
}

你是说 继承自 类型 T 的任何东西都是可以接受的。

您可以使用map定义您自己的扩展类型的方法:

public static <U, T extends U> U orElse(Optional<T> tOpt, U u) {
    return tOpt.<U>map(Function.identity()).orElse(u);
}