动机
我有一个 Either<L, R>
类,表示两种类型之一的值,或语义不同的状态。在某些情况下,无论值是哪个备选方案,对其进行操作都是有值(value)的。
问题
我想要一个采用 Consumer<T>
的(非静态)方法, 其中T
是 L
的父类(super class)型和 R
, 其中L
和 R
是类的类型参数。
目前,java 让我这样做:(静态实现)
public static <T, L extends T, R extends T> void collapse(Either<L,R> e, Consumer<T> op)
当然,对于非静态实现,我不能对 L
施加约束。和 R
,因为它们已经为相关实例定义。我需要对 T
施加的那些约束相反,但 java 不允许我编写以下内容,因为它一次只允许父类(super class)型或子类型约束中的一个类。这尤其令人沮丧,因为所有类至少共享 Object
作为常见的父类(super class)型,因此这些约束总是可满足的。
public void collapse(Consumer<? super L & R> op)
是否有任何其他方式来定义此约束,是否有任何暗示它在更高版本的 java 中被允许,或者是否有任何解释为什么它会成为一个破坏性功能?
最佳答案
在您的静态版本中,由于您需要消费者能够接受“L”或“R”类型,因此您实际上并不需要这些类型变量:Either<? extends T, ? extends T> e
.
但除此之外,我想说您的静态版本确实是您能做的最好的。 Java 只是没有特别具有表现力的类型系统。
我不认为 Eran 的回答是一个特别好的解决方案(尊重),因为:
- 它对消费者产生了限制:你必须像你期望的那样使用一般的限制,除非你只使用
Object
(宽泛得令人恼火),你总能找到一个你希望它稍微宽松一点的案例; - 它引入了一个额外的类型参数任何地方你使用
Either
类型,即使您不需要使用消费者,因为您必须始终提供 3 个类型参数(即使它们是?
)。第三种类型的参数感觉很笨拙。
我看到静态版本唯一真正的缺点是调用约定有点笨拙:Either.collapse(anEither, aConsumer)
而不是 anEither.collapse(aConsumer)
.当然,前者稍微更冗长……但它可以满足您的需求,因此您可能不得不接受这种尴尬。
关于Java 将参数约束到公共(public)父类(super class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56618413/