为什么输入参数在方法中是相反的? [英] Why are input parameters contravariant in methods?

查看:89
本文介绍了为什么输入参数在方法中是相反的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是教程中的一些代码:

Here's some code from this tutorial:

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)
}

该教程说:


不幸的是,该程序无法编译,因为仅当类型变量仅在
协变位置中使用时,才可以使用协方差
注释。由于类型变量T作为方法前缀的参数类型
出现,因此此规则已被破坏。

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.

<$ c如何$ c> T 在 predend 和其他 T 引用中未处于协变位置( def头:T = h def尾:ListNode [T] = t ),显然是协变的吗?

How is T not in a covariant position in predend, and the other T references (def head: T = h and def tail: ListNode[T] = t), apparently, are covariant?

我要问的是为什么中的 T 放在不是协变的。 为什么Function [-A1,...,+ B]不能允许任何超类型作为参数?

What I'm asking is why T in prepend is not covariant. This is certainly not covered in Why is Function[-A1,...,+B] not about allowing any supertypes as parameters?, which seems to be what others have directed me to read.

推荐答案

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

Input parameters of methods are not in covariant positions but contravariant positions. Only the return types of methods are in covariant positions.

如果您对 ListNode 类的定义是 / strong>好,那么我可以这样编写代码:

If your defination of ListNode class were OK, then I could write code like this:

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"

看,如果参数协变位置,则容器始终可以容纳具有与实际类型相同祖先的另一种类型的值。 错误

See, if arguments were covariant positions, then a container could always hold values of another type which has the same ancestor of its real type, and this is definitely WRONG!

因此,指的是 scala.collection.immutable.List。:: ,您的类应定义为:

So, referring to the source code of scala.collection.immutable.List.::, your class should be defined as this:

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

The argument type A is a new type parameter which is lower bounded to T.

这篇关于为什么输入参数在方法中是相反的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆