4

ListNode示例,取自 Scalas 主页,如下所示:

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

使用这个类,我们可以创建如下对象:

val empty: ListNode[Null] = ListNode(null, null)
val strList: ListNode[String] = empty.prepend("hello")
                                     .prepend("world")
val anyList: ListNode[Any] = strList.prepend(12345)

如我们所见,我们可以在String节点前添加一个整数值。我想,这是可行的,因为类型参数U将被自动设置为Any,当给prepend方法提供整数时(因为Int不是 的超类型String)。

当尝试使用自己的下限示例时,我会收到错误消息:

scala> class E[T >: String]
defined class E

scala> new E[Any]
res1: E[Any] = E@135f0a

scala> new E[Int]
<console>:11: error: type arguments [Int] do not conform to class E's type param
eter bounds [T >: String]
      val res2 =
          ^
<console>:12: error: type arguments [Int] do not conform to class E's type param
eter bounds [T >: String]
              new E[Int]
                  ^

为什么Int这里的类型不会自动被视为示例Any中的类型ListNode


更新 1:这也有效(没有明确地说 newListNode应该是 type Any

scala> val empty: ListNode[Null] = ListNode(null, null)
empty: example.listNode.ListNode[Null] = ListNode(null,null)

scala> empty.prepend("hello").prepend("world")
res0: example.listNode.ListNode[java.lang.String] = ListNode(world,ListNode(hell
o,ListNode(null,null)))

scala> val strList: ListNode[String] = empty.prepend("hello").prepend("world")
strList: example.listNode.ListNode[String] = ListNode(world,ListNode(hello,ListN
ode(null,null)))

scala> strList.prepend(12345)
res1: example.listNode.ListNode[Any] = ListNode(12345,ListNode(world,ListNode(he
llo,ListNode(null,null))))
4

2 回答 2

7

您会收到上述错误,因为Int它不是String.

请注意,在上面的ListNode代码中,StringNull(请参阅类层次结构Any的超类型,并且是String(正如您正确指出的那样)的超类型。

我猜想混淆是由比较两个并不完全相同的操作引起的:new E[Int]使用类型参数实例化类Int,它不符合下限String,因此失败。

ListNode另一方面,在上面的代码中,您调用了prepend采用超类型U的方法T。创建时anyList, U(正如您所猜测的那样)解析为,Any因为这是 and 的唯一常见超类型StringInt因此您可以认为它并没有真正将 an 传递给它,而只是( 它也恰好是 typeInt的一些任意实例)。AnyInt

所以,

val anyList: ListNode[Int] = strList.prepend(12345)

也失败了,因为strList.prepend(12345)只能返回ListNode[Any]

于 2012-07-01T09:26:26.137 回答
1

您正在做一件根本不同的事情:传递Int类型。让我们打破原来的代码,例如:

scala> val anyList: ListNode[Any] = strList.prepend[Int](12345)
<console>:11: error: type arguments [Int] do not conform to method prepend's type parameter bounds [U >: String]
       val anyList: ListNode[Any] = strList.prepend[Int](12345)
                                                   ^

看?如果您指定Int它会中断。它在原始版本中起作用,因为12345被推断为 type Any,而不是 type Int

于 2012-07-01T17:40:56.987 回答