3

似乎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的行为是一致的,但是有什么理由做不到,有没有其他方法可以达到这个效果呢?

4

2 回答 2

2

T为了扩展 Rex Kerr 的评论,在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
于 2013-02-16T19:21:29.143 回答
2

类型系统从最严格的类型开始(即Nothing,其中不能有实例;如果有的话,它将是一个能够代表任何事情并做任何事情的神一般的值)。然后根据需要扩大类型,但由于返回处于逆变位置,因此没有理由扩大。如果您实际上可以返回 a Nothing,那么您将在所有情况下都被设置。

然后,您通过告诉类型系统0Nothing. 当然,这完全是错误的,但是编译器尽职尽责地相信您,并且您通过将其分配给 an 来挽救这种情况Int,这就是它一直以来的真实情况。(它也会很高兴地尝试将它分配给 a String,然后你会在运行时得到一个异常,因为此时它是无意义的。)

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

于 2013-02-16T19:25:55.627 回答