有没有办法在Scala反射中将两个等效类型转换为两个相同的类型?

时间:2012-12-27 19:57:06

标签: scala reflection scala-2.10

请考虑以下事项:

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[Boolean]
res23: reflect.runtime.universe.Type = Boolean

scala> typeOf[scala.Boolean]
res24: reflect.runtime.universe.Type = Boolean

scala> res23 == res24
res25: Boolean = true

scala> typeOf[java.lang.Boolean]
res26: reflect.runtime.universe.Type = Boolean

scala> res23 == res26
res27: Boolean = false

scala> class Foo { def bf(arg: Boolean) = ??? }
defined class Foo

scala> typeOf[Foo]
res28: reflect.runtime.universe.Type = Foo

scala> res28.member(newTermName("bf")).asMethod
res30: reflect.runtime.universe.MethodSymbol = method bf

scala> res30.paramss.head.head
res31: reflect.runtime.universe.Symbol = value arg

scala> res31.typeSignature
res32: reflect.runtime.universe.Type = scala.Boolean

scala> res32 == res23
res33: Boolean = false

scala> res32 =:= res23
res37: Boolean = true

因此,通过typeOf [Boolean]函数获得的类型等同于通过检查方法获得的类型,但它不相等。

有没有办法将两个等价类型转换为结果相等的规范表示?我希望能够将它们用于地图中的键。

编辑:

更清楚的是,我正在寻找的是(不是真正的repl会话):

scala>val tp1 = // some type
scala>val tp2 = // equivalent type obtained another way
scala>tp1 == tp2
res1: Boolean = false
scala>tp1 =:= tp2
res2: Boolean = true
scala>val ctp1 = tp1.canonical
scala>val ctp2 = tp2.canonical
scala>ctp1 == ctp2
res3: Boolean = true
scala>ctp1 =:= tp1
res4: Boolean = true
scala>ctp2 =:= tp2
res5: Boolean = true

因此,转换会保留等效性。我还需要它来处理参数化类型。

2 个答案:

答案 0 :(得分:4)

来自the documentation

  

重要的是要注意==不应该用于比较类型   等式 - ==在类型存在时无法检查类型是否相等   别名,而=:=可以。

您当然可以将类型存储在列表中并使用(例如)以下内容来检查包含:

myTypes.exists(_ =:= someType)

例如,您将在2.10编译器源中看到此方法。当然,它不如地图或集合那么高效,但是你通常在集合中没有很多这样的东西。

如果您必须具有地图或集合的效果,则可以使用erasure(如另一个答案所示)或typeSymbol,具体取决于您的要求。

答案 1 :(得分:2)

erasure

scala.reflect.api.Types.TypeApi方法:

typeOf[Foo].member(newTermName("bf")).asMethod.paramss.head.head
  .typeSignature.erasure == typeOf[Boolean]
// res21: Boolean = true