不是所有类型的子类型都不是吗?
scala> val array = new Array(5)
array: Array[Nothing] = Array(null, null, null, null, null)
scala> array.map(_ => 42)
<console>:9: error: value map is not a member of Array[Nothing]
array.map(_ => 42)
^
scala> array.filter(_ != 42)
<console>:9: error: value filter is not a member of Array[Nothing]
array.filter(_ != 42)
^
奇怪的是,这不起作用。
这是指定的,功能还是错误?
答案 0 :(得分:7)
当你看到涉及Nothing的奇怪行为时,这是因为类型推断算法认为它本身插入了Nothing,因为它是在类型推断期间引入的:如果对类型变量一无所知,则它由Any和Nothing限定。长期以来一直在我要做的事情列表中,看看我是否可以为此目的引入一个新的仅内部底部类型,因此用户级别Nothing和推理级别没有任何内容没有混合,但这是一项非常雄心勃勃的任务。不过,我现在可能已经足够努力了。
答案 1 :(得分:4)
我怀疑Scala不应该让你做那种Array[Nothing]
实例化。根据定义,没有任何实例,但是你的数组看起来像是Nothing
,它们是空的,但是null不是Nothing
的有效值。例如,这失败了,错误为type mismatch; found : Null(null) required: Nothing
val n: Nothing = null
因此,每次你真的欺骗系统时,我都会遇到麻烦,相信你最终会抓住一个备受追捧的Nothing
......
这是另一个奇怪的案例。运行这个:
object Main {
class Parametrized[T] { var value: T = _ }
def main(args: Array[String]) {
val p = new Parametrized // typed as Parametrized[Nothing]
val n = p.value // n is now actually an instance of Nothing... isn't it?
println(p.value) // prints null, but null is not an instance of Nothing
println(n) // throws NullPointerException...
}
}
答案 2 :(得分:4)
请注意,Scala数组类型是不变的。因此Nothing
是所有事物的子类型可能不相关。
map
上未定义filter
和Array
。 Predef
中的隐式转换用于为数组提供此类方法。
因此,编译器无法找到从Array[Nothing]
到已定义map
或filter
的内容的隐式转换。使用REPL,我实际上可以看到这样的隐式转换应该可用:
scala> val conv = implicitly[Array[Nothing] <%< collection.mutable.ArrayOps[Nothing]]
conv: <%<[Array[Nothing],scala.collection.mutable.ArrayOps[Nothing]] = <function1>
scala> conv(new Array[Nothing](5)).filter(_ => true)
res8: Array[Nothing] = Array(null, null, null, null, null)
所以问题就变成了编译器不考虑genericArrayOps
转换的原因。