Freewind @ Thoughtworks scala java javascript dart 工具 编程实践 月结 math python english [comments admin] [feed]

(2014-07-23) 为什么Nil的类型是List[Nothing],而不是List[Any]

广告: 云梯:翻墙vpn (省10元) 土行孙:科研用户翻墙http proxy (有优惠)

今天在做scala workshop讲到Nil的类型时,杜娟提了一个很好的问题:为什么Nil的类型是List[Nothing],而不是List[Any]

首先看Nil的定义:

case object Nil extends List[Nothing] {
  ..
}


对于Scala的List来说,它是不可变的,不会往里面添加东西。这样的话,它的类型是List[Nothing]还是List[Any]似乎都没什么区别才对。

让我们从类型系统方面考虑一下,很快就能知道原因。

我们定义一个List的时候,可以使用这样的方式:

val list = 1 :: 2 :: Nil


它实际上等于:

val list = Nil.::(2).::(1)


让我们看一下`::`的定义(简化了):

class List[+A] {
  def ::[B >: A] (x: B): List[B] =
    new scala.collection.immutable.::(x, this)
}


再看一下`immutable.::`的定义:

case class ::[B](hd: B, tl: List[B])


可见`::[B]`中B的类型,将由传入的两个参数`hd`和`tl`的公共父类决定。如果Nil继承自List[Any],那么:

Nil.::(1)


即:

::(1, Nil)

的类型,将是IntAny的父类,即Any。这样的话,我们不论怎么写,都只能得到List[Any]类型的List,显然是没有意义的。

但反过来,如果Nil继承自List[Nothing],由于Nothing是任意类型的子类,所以它与另一个类型的公共父类型总是另一个类型,所以我们就可以轻易由另一个类型来确定List的类型了。

comments powered by Disqus