给出如下的API:
class Bar { ... }
class Foo extends Bar { ... }
在Java的Optional
类型中,我们可以说:
Optional<Foo> fooOption = ...
fooOption.orElse(aFoo) // returns something of type Foo
但是,由于Foo
是Bar
,我希望能够说:
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);
}
我如何重写这个以进行编译,还支持同时在需要时扩展类型的能力?
答案 0 :(得分:6)
但是,由于
Foo
是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());
答案 1 :(得分:3)
由于U
应该是T
的超类型,您可以这样做:
public abstract class Option<U, T extends U> {
public abstract of(T value);
public abstract U orElse(U other);
}
答案 2 :(得分:3)
您可以使用map
定义自己的方法来扩展类型:
public static <U, T extends U> U orElse(Optional<T> tOpt, U u) {
return tOpt.<U>map(Function.identity()).orElse(u);
}
答案 3 :(得分:2)
在你的问题中有一个基本前提是有缺陷的:
在Java的Optional类型中,我们可以说:
可选fooOption = ... fooOption.orElse(aFoo)//返回类型为Foo的东西 但是,既然Foo是一个酒吧,我想能够说:
可选fooOption = ... fooOption.orElse(aBar)//返回类型为Bar
的东西
A Foo是一个酒吧,但酒吧不是Foo。如果你的Generic被定义为:
Optional<Foo> fooOption = ...
然后您可以返回Foo
类型的任何内容。 Bar
类型为Foo
的
如果您有其他对象:
class FooBar extends Foo{}
然后你可以在你的例子中将它转换为foo:
可选fooOption = ...
fooOption.orElse(aFooBar)//返回类型为Foo的东西
或者,或者,如果您已将Optional
定义为Optional<Bar>
,则可以使用Foo
或Bar
或FooBar
个对象,因为它们是全部或继承自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的任何内容都是可以接受的。