回顾 Java 8 Stream
API 设计,我对参数的通用不变性感到惊讶Stream.reduce()
:
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
同一个 API 的一个看似更通用的版本可能对 的各个引用应用了协变/逆变U
,例如:
<U> U reduce(U identity,
BiFunction<? super U, ? super T, ? extends U> accumulator,
BiFunction<? super U, ? super U, ? extends U> combiner)
这将允许以下情况,目前这是不可能的:
// Assuming we want to reuse these tools all over the place:
BiFunction<Number, Number, Double> numberAdder =
(t, u) -> t.doubleValue() + u.doubleValue();
// This currently doesn't work, but would work with the suggestion
Stream<Number> stream = Stream.of(1, 2L, 3.0);
double sum = stream.reduce(0.0, numberAdder, numberAdder);
解决方法,使用方法引用将类型“强制”为目标类型:
double sum = stream.reduce(0.0, numberAdder::apply, numberAdder::apply);
C# 没有这个特殊问题,Func(T1, T2, TResult)
定义如下,使用声明站点差异,这意味着任何使用的 APIFunc
都可以免费获得此行为:
public delegate TResult Func<in T1, in T2, out TResult>(
T1 arg1,
T2 arg2
)
与建议的设计相比,现有设计有哪些优势(可能还有 EG 决策的原因)?
或者,换一种方式问,我可能忽略的建议设计的注意事项是什么(例如类型推断困难、并行化约束或特定于归约操作的约束,例如关联性、对未来 Java 声明站点差异的预期BiFunction<in T, in U, out R>
, ...)?