gpt4 book ai didi

scala - 为什么输入参数在方法中是逆变的?

转载 作者:行者123 更新时间:2023-12-01 11:33:15 25 4
gpt4 key购买 nike

这是来自 this 的一些代码教程:

case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend(elem: T): ListNode[T] =
ListNode(elem, this)
}

教程说:

Unfortunately, this program does not compile, because a covariance annotation is only possible if the type variable is used only in covariant positions. Since type variable T appears as a parameter type of method prepend, this rule is broken.

T怎么不在predend中的协变位置,而其他T引用(def head: T = h def tail: ListNode[T] = t), 显然是协变的?

我要问的是为什么 prepend 中的 T 不是协变的。这当然不在Why is Function[-A1,...,+B] not about allowing any supertypes as parameters?中。 ,这似乎是其他人指示我阅读的内容。

最佳答案

方法的输入参数不是协变的,而是逆变的。只有方法的返回类型处于协变位置。

如果您对ListNode 类的定义 OK,那么我可以编写如下代码:

val list1: ListNode[String] = ListNode("abc", null)
val list2: ListNode[Any] = list1 // list2 and list1 are the same thing
val list3: ListNode[Int] = list2.prepend(1) // def prepend(elem: T): ListNode[T]
val x: Int = list3.tail.head // ERROR, x in fact is "abc"

看,如果参数协变位置,那么容器总是可以保存另一种类型的值,该类型与其真实类型具有相同的祖先,这绝对是错误 !

所以,引用scala.collection.immutable.List.::的源码,你的类应该定义为:

case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend[A >: T](elem: A): ListNode[A] = ListNode(elem, this)
}

参数类型 A 是一个新的类型参数,下界为 T

关于scala - 为什么输入参数在方法中是逆变的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30365846/

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