为什么 Promise 不能是协变的?

7

有一个简单的规则:如果你可以从中获取一个值,那么它是协变的(例如:Try、Future、List、Vector、Option等)。如果你可以将一个值放入其中,那么它就是逆变的(例如:Promise、Ordering、Consumer等)。 - ZhekaKozlov
2个回答

8
如果 Promise 是协变的,你可以这样做:

如果承诺是协变的,您可以执行以下操作:

val p: Promise[Any] = Promise[String]()
p.success(1)

因此,使用一个不安全的方法,可以完成将Int转化为Promise[String]的过程。


3

一个 Promise 是一个可变的 API,它在协变方面表现不佳。Future 不会遇到这个问题,因为你不能像使用 Promise 一样手动完成它们。

假设我们有:

class Animal
class Cat extends Animal
class Dog extends Animal

如果你希望Promise[A]上是协变的,那就意味着我们想要Promise[Cat] <: Promise[Animal]Promise[Dog] <: Promise[Animal]。假设我们可以这样做。

好的,现在假设我们有一个Promise[Cat]

val p: Promise[Cat] = ...

根据我们的假设,它也是一个Promise[Animal]

val q: Promise[Animal] = p

Promise有一个名为complete的方法,它接受一个Try[T],这也是协变的。这意味着一个Try[Dog]也是一个Try[Animal]。你看到这个要点了吗?

我们就可以调用:

val value: Try[Dog] = ...

q.complete(value)

这将是合法的,因为我们正在尝试使用Try[Animal]完成一个Promise[Animal],但是糟糕,我们还尝试使用Promise[Dog]完成一个Promise[Cat]

1
可变性在这里不是一个问题。我认为Promise可以被制作成逆变。 - ZhekaKozlov
@ZhekaKozlov 这绝对是协方差的问题,这也是问题所在。 - Michael Zajac
这是协方差的问题,但不是方差的问题。 - ZhekaKozlov
谢谢你详细的回答。但是我会接受@Lee的答案,因为他的回答比你早1分钟,并且本质上是一样的 :)。 - Dominic N.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接