16

scala 类型Nothing代表(据我所知)类型层次结构的底部,也用符号 ⊥ 表示。也就是说,Nothing是任何给定类型的子类型。James Iry为我们这些没有类型理论理论背景的人很好地解释了Nothing类型的要求!

所以我的问题是,如果Nothing是每种类型的子类型,为什么我不能调用任何类型的方法Nothing?显然,我不能实例化 Nothing 但为什么下面的代码不编译?

var n: Nothing = _

def main(args: Array[String]) {
  println(n.length) //compile error: value length is not a member of Nothing
}

当然,这Nothing是一个子类型String应该可以吗?请注意,以下编译得很好!

var n: Nothing = _

def foo(s: String) : Int =  s.length

def main(args: Array[String]) {
  println(foo(n))
}

一样:

def main(args: Array[String]) {
  println(n.asInstanceOf[String].length) 
}
4

3 回答 3

18

虽然Nothing是一切的子类型,但它不继承任何方法,除了Any. 这是因为Nothing它更适合语言的功能端。它对于像Optionand之类的东西是必要的List,但只能作为一种类型,而不是作为一个类。

对于那些来自面向对象背景的人来说,这里的区别有点奇怪,但事实是子类型作为一个概念与 OOP 非常不同。诚然,面向对象确实意味着某种形式的子类型化,但反之则不然。Benjamin Pierce 的Types and Programming Languages很好地展示了语言F _<(发音为“F sub”),它作为具有子类型(但不是 OO)的语言的最小示例。

现在,尽管如此,我确实同意Nothing不受正常继承规则影响的事实似乎有点不一致。但是,从理论的角度来看,这是完全合理的。

于 2009-11-13T14:49:00.107 回答
2

我想Nothing可以接受任何方法,并对所有方法执行标准操作(抛出异常)。不过,那不会很有用。

通过呈现编译错误,编译器警告程序员,他很可能不想要的类型,Nothing在代码中的某个点以某种方式被推断出来。

于 2009-11-13T12:28:10.687 回答
0

您可以调用变量toStringNothing因为它的定义:
final trait Nothing extends Any
并且 toString 是Any. 我认为 scala 编译器Nothing只处理类型边界,并将其视为所有情况下的任何其他特征。我认为让调用类型为 of 的变量的任何方法Nothing会很奇怪。

于 2009-11-13T14:02:49.243 回答