Scala 隐式 TypeTag 无法正确传播(隐式类型为 Nothing)



我在代码中广泛使用scala的2.10 TypeTags,我观察到一些与类型推断相关的行为,我不理解。

示例代码:

import scala.reflect.runtime.universe._
object BugDemo extends App {
  def printType[T <: AnyRef : TypeTag]() : T = { 
    println(typeOf[T]); 
    null.asInstanceOf[T]; 
  }
  case class Foo()
  var foo1 = printType[Foo]()
  var foo2 : Foo = printType[Foo]()
  var foo3 : Foo = printType()
}

现在我希望它打印 Foo 3 次,但实际上我得到 (scala 2.10.3):

BugDemo.Foo
BugDemo.Foo
Nothing

我的代码有什么问题?为什么 scala 不想在 foo3 中为我的T传递正确的类型标签?

这里没有错。

未指定类型参数的情况下,scala 编译器采用最具体的类型。在printType()的情况下,它是Nothing(scala 类型层次结构中的底部类型)。

由于NothingFoo代码有效的子类型:

var foo3 : Foo = printType[Nothing]()

有趣的是,有了var foo3 : Nothing = printType[Nothing]()甚至printType[Nothing](),你都会得到一个NullPointerException

scala> var foo3 : Nothing = printType[Nothing]()
Nothing
java.lang.NullPointerException
scala> printType[Nothing]()
Nothing
java.lang.NullPointerException

你无法获得Nothing的实例,但是你的代码(var foo3 : Foo = printType[Nothing]())由于类型擦除而工作。它看起来像一个无法修复的 scala 错误。

当调用方未显式提供类型参数时,scala 推断的类型参数没有任何内容。我讨厌(讨厌)这种默认行为,因为它会导致各种运行时错误,没有什么是所有内容的允许参数。

最好通过要求类型参数不是 Nothing,在编译时完全指定类型参数:

sealed trait NotNothing[-T] 
object NotNothing {
  implicit object YoureSupposedToSupplyAType extends NotNothing[Nothing]
  implicit object notNothing extends NotNothing[Any] 
}

然后:

def printType[T : TypeTag : NotNothing]() : T = { ... }

相关内容

最新更新