问题
It seems that TypeTags
only work for type parameters that are used in the parameters of the called method, and not the return type:
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
This is consistent with the behaviour of Manifest in 2.9, but is there any reason it can't be done, and is there any other way to achieve this effect?
回答1:
The type system starts with the most restrictive type (i.e. Nothing
, of which there can be no instances; if there were it would be a godlike value able to stand in for anything and do anything). The type is then widened as needed, but since the return is in contravariant position, there's never a reason to widen. If you actually could return a Nothing
, you'd be set in all situations.
You then subvert the type system by telling it that 0
is an instance of Nothing
. It's completely false, of course, but the compiler dutifully believes you, and you rescue the situation by assigning it to an Int
, which is what it really was all along. (It will also happily try to assign it to a String
and you'll then get an exception at runtime because at that point it is nonsensical.)
In theory this could be done differently, but this is a pretty basic part of the type inference algorithm.
回答2:
To expand on Rex Kerr's comment, there is nothing do drive inference of T
in the justReturn
case. If you supply a (suitable) type parameter, you get this:
scala> val j: Int = Test.justReturn[Int]()
Int
j: Int = 0
If you change justReturn
to this:
def justReturn[T: TypeTag]() {
println(typeOf[T])
}
... then you can do this:
scala> justReturn[String]()
String
scala> justReturn[java.io.File]()
java.io.File
来源:https://stackoverflow.com/questions/14913746/why-does-typetag-not-work-for-return-types