: A](v: B)"这样定义的方法接受不是 A 父类(super class)型的类型参数?-6ren"> : A](v: B)"这样定义的方法接受不是 A 父类(super class)型的类型参数?-我现在正在研究 Scala 中的方差,我想我对逆变有很好的理解。例如给定 trait List[-A] ,我知道List[Int]是 List[AnyVal] 的父类(super class)型. 但-6ren">
gpt4 book ai didi

scala - 为什么像 "cons[B >: A](v: B)"这样定义的方法接受不是 A 父类(super class)型的类型参数?

转载 作者:行者123 更新时间:2023-12-04 18:33:00 26 4
gpt4 key购买 nike

我现在正在研究 Scala 中的方差,我想我对逆变有很好的理解。例如给定 trait List[-A] ,我知道List[Int]List[AnyVal] 的父类(super class)型.

但是说我有以下特点:

trait List[+A] {
def cons(hd: A): List[A]
}

为什么是 cons参数类型错误?

为什么一定要有 def cons[B >: A](v: B): List[B] ?

例如:
val animal_list: List[Animal] = List(tiger, dog)

如果我们调用:
animal_list.cons(tiger)

Tiger <: Animal , 没有 cons遇到问题? BTigerAAnimalB >: A不是真的。

最佳答案

为什么是 cons的参数类型不对?

trait List[+A] {
def cons(hd: A): List[A]
}

编译器给你错误: covariant type A occurs in contravariant position in type A of value hd 因为方法参数算作逆变位置,但是 A是协变的。

让我们想象一下这个方法声明会编译。然后我们可以这样做:
class ListImpl[A] extends List[A] {
override def cons(hd: A): List[A] = ???
}

val strings: List[String] = new ListImpl[String]
val values: List[Any] = strings // OK, since List[String] <: List[Any] (in List[A], A is covariant)
values.cons(13) // OK(??), since values's static type is List[Any], so argument of cons should be Any, and 13 conforms to type Any

上面最后一行真的好吗?我们正在调用 consvalues . valuesstrings 相同, 和 stringsListImpl[String] 类型的对象.所以 cons最后一行中的调用正在等待 String争论,但我们正在通过 Int , 因为 values的静态类型是 List[Any]Int符合 Any .这里肯定有问题 - 应该归咎于哪条线?答案是: cons方法声明。为了解决这个问题,我们必须删除协变类型参数 A从逆变位置(在 cons 声明中)。或者,我们可以制作 A非协变。

另请参阅以下问题: #1 , #2 .

... 没有 cons遇到问题?
trait List[+A] {
def cons[B >: A](v: B): List[B]
}

val animal_list: List[Animal] = List(tiger, dog) // We are assuming that List.apply and concrete implementation of List is somewhere defined.

不,animal_list.cons(tiger)调用是类型正确的。

我假设 AnimalDog 的常见父类(super class)型和 Tiger ,以及 dogtigerDog 的实例和 Tiger分别。

animal_list.cons(tiger)调用,两者 AB类型参数实例化为 Animal , 所以 cons方法采用以下形式:
def cons[Animal >: Animal](v: Animal): List[Animal]
Animal >: Animal满足约束是因为:

Supertype and subtype relationships are reflexive, which means a type is both a supertype and a subtype of itself. [source]


cons 的参数是 Tiger符合类型 Animal ,所以方法调用是类型正确的。

请注意,如果您强制 B要实例化为 Tiger , 喜欢 animal_list.cons[Tiger](tiger) ,那么此调用将不会是类型正确的,并且您将收到编译器错误。

查看类似示例 here .

关于scala - 为什么像 "cons[B >: A](v: B)"这样定义的方法接受不是 A 父类(super class)型的类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37334674/

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