gpt4 book ai didi

scala - 协变类型 A 出现在值 a 的类型 A 中的逆变位置

转载 作者:行者123 更新时间:2023-12-03 10:33:51 25 4
gpt4 key购买 nike

我有以下类(class):

case class Box[+A](value: A) {

def set(a: A): Box[A] = Box(a)

}

编译器提示:
Error:(4, 11) covariant type A occurs in contravariant position in type A of value a
def set(a: A): Box[A] = Box(a)

我搜索了很多关于错误的信息,但找不到有用的东西
帮助我理解错误。

有人可以解释一下,为什么会发生错误?

最佳答案

一旦你理解它,错误信息实际上非常清楚。让我们一起到达那里。
您正在声明类 Box作为其类型参数中的协变 A .这意味着对于任何类型 X延伸 A (即 X <: A)、Box[X]可以看作是Box[A] .
为了给出一个明确的例子,让我们考虑 Animal类型:

sealed abstract class Animal
case class Cat extends Animal
case class Dog extends Animal
如果您定义 Dog <: AnimalCat <: Animal ,然后两者 Box[Dog]Box[Cat]可以看成 Box[Animal]你可以例如创建一个包含这两种类型的集合并保留 Box[Animal]类型。
尽管此属性在某些情况下非常方便,但它也对您可以在 Box 上提供的操作施加了限制。 .这就是为什么编译器不允许你定义 def set .
如果你允许定义
def set(a:A): Unit
那么下面的代码是有效的:
val catBox = new Box[Cat]
val animalBox: Box[Animal] = catBox // valid because `Cat <: Animal`
val dog = new Dog
animalBox.set(dog) // This is non-sensical!
最后一行显然有问题,因为 catBox现在将包含 Dog !方法的参数出现在所谓的“逆变位置”中,这与协方差相反。事实上,如果你定义 Box[-A] ,然后 Cat <: Animal暗示 Box[Cat] >: Box[Animal] ( Box[Cat]Box[Animal] 的父类(super class)型)。对于我们的示例,这当然是无意义的。
解决您的问题的一种方法是制作 Box类不可变(即不提供任何方法来更改 Box 的内容),而是使用您的 case class 中定义的 apply 方法创建新盒子的伴侣。如果需要,也可以定义 set本地而不是将其暴露在任何地方之外 Box通过将其声明为 private[this] .编译器将允许这样做,因为 private[this]保证我们错误示例的最后一行不会编译,因为 set方法在 Box 的特定实例之外完全不可见.
如果由于某种原因您不想使用 apply 方法创建新实例,您还可以定义 set如下。
def set[B >: A](b: B): Box[B] = Box(b)

关于scala - 协变类型 A 出现在值 a 的类型 A 中的逆变位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43180310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com