什么时候没有合法收货人?

时间:2018-06-26 12:13:04

标签: scala inheritance types subtyping bottom-type

成为subtype of every other type允许将假设的Nothing类型的值传递给任何函数。但是,尽管这样的值可以作为toString()的接收者,但不能作为unary_!(以及其他)的接收者。

object Foo {
    def dead(q: Nothing): Unit = {
        println(q);
        q.toString();
        ((b: Boolean) => !b)(q);
        !q; // value unary_! is not a member of Nothing
    }
}

这是错误还是功能?

注意:

  1. 这是equivalent question I asked on Kotlin的Scala版本。
  2. 上传工作:!(q.asInstanceOf[Boolean])

2 个答案:

答案 0 :(得分:2)

您不需要上流。您只需将某种具有方法unary_!的类型归因于此:

def dead(q: Nothing): Unit = {
  !(q: Boolean)
}

没有显式类型说明,方法unary_!根本无法解析,因为即使NothingBoolean子类型,它也不是< Boolean的em> subclass ,因此编译器无法在unary_!的继承层次结构中找到方法Nothing

您可以定义此类方法和函数的事实也不是错误。以下是一个完全有效的程序,该程序使用输入类型为Nothing的函数来产生完全有意义的结果0,而不会引发任何错误或类似的结果:

def foo[X](xs: List[X], f: (Int, X) => Int) = {
  xs.foldLeft(0)(f)
}

foo(Nil, (i: Int, n: Nothing) => 42)

在类型系统中存在Nothing是一个非常好的主意,因为它是一个初始对象(对于每个其他类型A,只有一个功能Nothing => A),并且它简化了很多事情,因为它不会强迫您处理各种奇怪的极端情况。

答案 1 :(得分:0)

  

是其他所有类型的子类型(包括scala.Null);没有这种类型的实例

换句话说,没有类型Nothing的值。因此,与您的问题中的陈述相反,您不能将Nothing类型的值传递给任何函数(甚至假设地),因为根据定义,它不存在。同样,它也不是任何方法的接收者,因为它再次不存在。

因此,该错误(如果有的话)是编译器不会警告您您创建了一个永远无法调用的函数。


在这种情况下,println(q)起作用是因为NothingAny的子类型,而q.toString起作用是由于AnyRef到{{ 1}}支持Object。内联函数将toString转换为q也可以,但是Boolean不支持Object,因此unary_!无法编译。