【问题标题】:When is Nothing a legal receiver?什么时候没有合法的接收者?
【发布时间】:2018-06-26 12:13:04
【问题描述】:

作为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])

【问题讨论】:

  • 一般来说,子类型化 != 继承,尽管大多数 OOP 主流语言倾向于混淆它,因此这两个概念看起来几乎是同义词。
  • 假设您可以调用任何可能在 Nothing 类型的变量上定义的方法,允许这样的程序有什么好处?

标签: scala inheritance types subtyping bottom-type


【解决方案1】:

你不需要向上转换。您只需要指定具有unary_! 方法的某种类型:

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

如果没有明确的类型归属,方法unary_! 根本无法解析,因为即使Nothing 是Boolean 的子类型,它也不是子类 的Boolean,因此编译器在Nothing 的继承层次结构中找不到方法unary_!。

您可以定义这样的方法和函数这一事实也不是错误。以下是一个完全有效的程序,它使用输入类型为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),它简化了很多事情,因为它不会强迫你处理各种奇怪的极端情况。

【讨论】:

  • 同意子类型化!=继承。但是,子类型化意味着Bool 类型的术语可以被Nothing 类型的术语替换。为什么这在表达式 !q 中不可能?
  • @cuihtlauac in "term of type Bool"有两部分:term和type Bool 。您可以将 term 替换为 q,但您仍然必须在某处指定 type Bool。如果你的q 是Nothing 类型,那么编译器不可能推断你在编写!q 时引用了Bool::unary_! 方法。子类型关系决定了你可以用什么来代替什么。继承关系决定了在哪些类中查找方法。
【解决方案2】:

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

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

因此,如果存在错误,编译器不会警告您创建了一个永远无法调用的函数。


在这种情况下,println(q) 起作用是因为Nothing 是Any 的子类型,而q.toString 起作用是因为AnyRef 到Object 的隐式转换支持toString。内联函数将q转换为Boolean也可以,但是Object不支持unary_!所以!q编译失败。

【讨论】:

  • 很好,那为什么前三个使用 q 合法而第四个不合法?
  • 我想这是因为 Java Object 和 Scala Any 之间的不安关系,编译器会做一些软糖来使事情正常进行。具体来说,我怀疑从Any 到Object 之间存在隐含,因此toString 有效,但! 无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多