Scala 什么时候不是合法的接收人?
作为允许将假定的Scala 什么时候不是合法的接收人?,scala,inheritance,types,subtyping,bottom-type,Scala,Inheritance,Types,Subtyping,Bottom Type,作为允许将假定的Nothing类型化值传递给任何函数。然而,尽管这样一个值可以作为toString()的接收器,但它不能作为一元数组的接收器(除其他外) 这是一个bug还是一个特性 注: 这是一个的Scala版本 上传作品:!(q.asInstanceOf[Boolean]) Nothing是所有其他类型(包括scala.Null)的子类型;不存在此类型的实例 换句话说,没有类型为Nothing的值。因此,与您问题中的陈述相反,您不能将Nothing类型化值传递给任何函数(即使是假设的),因为根
Nothing
类型化值传递给任何函数。然而,尽管这样一个值可以作为toString()
的接收器,但它不能作为一元数组的接收器代码>(除其他外)
这是一个bug还是一个特性
注:
这是一个的Scala版本
上传作品:!(q.asInstanceOf[Boolean])
Nothing是所有其他类型(包括scala.Null)的子类型;不存在此类型的实例
换句话说,没有类型为Nothing
的值。因此,与您问题中的陈述相反,您不能将Nothing
类型化值传递给任何函数(即使是假设的),因为根据定义,它不存在。它也不能成为任何方法的接收者,因为它同样不存在
因此,如果有一个bug的话,那就是编译器没有警告您已经创建了一个永远无法调用的函数
在这种情况下,println(q)
工作是因为Nothing
是Any
的子类型,而q.toString
工作是因为AnyRef
隐式转换为对象,该对象支持toString
。内联函数将q
转换为Boolean
,这也可以,但是Object
不支持一元数代码>所以!q
无法编译。您不需要向上转换。您只需指定某个类型,该类型有一个方法一元数\代码>:
def dead(q: Nothing): Unit = {
!(q: Boolean)
}
如果没有显式的类型归属,那么方法unary\ux
根本无法解析,因为即使Nothing
是Boolean
的子类型,它也不是Boolean
的子类,因此编译器无法找到方法一元在继承层次结构中的无
事实上,您可以定义这样的方法和函数也不是一个bug。以下是一个完全有效的程序,它使用输入类型为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
),它简化了很多事情,因为它不会强迫您处理所有奇怪的角落情况。好,那么为什么q的前三个用法是合法的,而第四个用法是不合法的呢?我想这是因为JavaObject
和ScalaAny
之间存在着不稳定的关系,编译器在这两种关系中做了一些修改以使事情正常工作。具体来说,我怀疑有一个隐式的fromAny
toObject
,因此toString
可以工作,但是代码>没有。通常,子类型!=继承,即使大多数OOP主流语言倾向于将其混淆,因此这两个概念看起来几乎是同义的。假设您可以调用任何可能在类型为Nothing
的变量上定义的方法,允许这样的程序有什么好处?同意子类型!=遗产但是,子类型表示Bool
类型的术语可以替换为Nothing
类型的术语。为什么这在表达式中不可能!q
?@cuihtlauac在“布尔型术语”中有两部分:布尔型术语和布尔型术语。您可以将术语替换为q
,但仍然必须在某个地方指定类型Bool。如果您的q
类型为Nothing
,则编译器不可能推断您引用的是方法Bool::unary代码>当您编写时!q
。它的子类型关系决定了你可以用什么来代替什么。继承关系决定了在哪些类中查找方法。
def foo[X](xs: List[X], f: (Int, X) => Int) = {
xs.foldLeft(0)(f)
}
foo(Nil, (i: Int, n: Nothing) => 42)