为什么TypeTag不适用于返回类型?

时间:2013-02-16 18:40:04

标签: scala scala-2.10

似乎TypeTags仅适用于被调用方法的参数中使用的类型参数,而不适用于返回类型:

scala> :paste
// Entering paste mode (ctrl-D to finish)

import scala.reflect.runtime.universe._

object Test {
  def withParam[T: TypeTag](v: T): T = {
    println(typeOf[T])
    0.asInstanceOf[T]
  }

  def justReturn[T: TypeTag](): T = {
    println(typeOf[T])
    0.asInstanceOf[T]
  }
}

// Exiting paste mode, now interpreting.

import scala.reflect.runtime.universe._
defined module Test


scala> val i: Int = Test.withParam(17)
Int
i: Int = 0

scala> val j: Int = Test.justReturn()
Nothing
j: Int = 0

这与2.9中Manifest的行为一致,但有什么理由不能完成,还有其他方法可以达到这个效果吗?

2 个答案:

答案 0 :(得分:2)

要扩展Rex Kerr的评论,T案例中justReturn的驱动推断没有任何内容。如果你提供(合适的)类型参数,你得到这个:

scala> val j: Int = Test.justReturn[Int]()
Int
j: Int = 0

如果您将justReturn更改为:

def justReturn[T: TypeTag]() {
  println(typeOf[T])
}

...然后你可以这样做:

scala> justReturn[String]()
String

scala> justReturn[java.io.File]()
java.io.File

答案 1 :(得分:2)

类型系统以最严格的类型(即Nothing开始,其中不存在任何实例;如果存在,它将是一个神圣的价值能够代替任何东西并做任何事情)。然后根据需要扩大类型,但由于返回处于逆变位置,因此没有理由扩大。如果您确实可以返回Nothing,则可以在所有情况下进行设置。

然后通过告诉0Nothing的实例来破坏类型系统。当然,这是完全错误的,但是编译器尽职尽责地相信你,并且通过将它分配给Int来拯救这种情况,这就是它一直以来的真实情况。 (它也会愉快地尝试将它分配给String,然后你会在运行时获得异常,因为那时它是荒谬的。)

理论上可以采用不同的方式,但这是类型推理算法的一个非常基本的部分。