给定 `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
但是,由于 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);
}
我如何重写它来编译,同时支持在需要时扩大类型的能力?
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>
,那么您可以使用 Foo
或 Bar
或 FooBar
对象,因为它们都是类型 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);
}
给定一个 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);
}
我如何重写它来编译,同时支持在需要时扩大类型的能力?
But, since
Foo
is aBar
但是 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>
,那么您可以使用 Foo
或 Bar
或 FooBar
对象,因为它们都是类型 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);
}