2012-09-17 59 views
7

給定一個類型聲明,我能夠解析類型參數。使用scala 2.10反射的類型自變量的運行時解析

scala> reflect.runtime.universe.typeOf[List[Int]] match {case x:TypeRef => x.args} 
res10: List[reflect.runtime.universe.Type] = List(Int) 

對於運行時值,同樣的方法不起作用。

scala> reflect.runtime.currentMirror.reflect(List(42)).symbol.toType match {case x:TypeRef => x.args} 
res11: List[reflect.runtime.universe.Type] = List(B) 

有沒有辦法克服反射值的類型擦除?

+0

也許你可以找到一個可行的解決方案後閱讀[這個答案](http://stackoverflow.com/a/1094214/315306) – Raffaele

+0

@Raffaele。感謝您的參考。不幸的是,這個問題(和答案)處理的是類型具體且在編譯期間已知的情況。清單已被棄用,TypeTags(取代清單)需要具體的標籤。 –

+1

使用AbsTypeTag(在RC1中重命名爲WeakTypeTag)。更多信息在這裏:http://stackoverflow.com/questions/12218641/scala-2-10-what-is-a-typetag-and-how-do-i-use-it –

回答

6

一個例子基於TypeTag知識閱讀 Scala: What is a TypeTag and how do I use it? 發佈獲得通過 Eugene Burmako在你的問題的意見:

import scala.reflect.runtime.universe._ 

object ScalaApplication { 
    def main(args: Array[String]) { 
    printType(List(42)) 
    printType(List("42")) 
    printType(List("42", 42)) 
    }  

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

這應該給輸出:

$ scala ScalaApplication.scala 
List[Int] 
List[String] 
List[Any] 

[UPDATE 1:]

然而,如果你想知道分配給類型的引用類型的Any您可能必須選擇某種類型意識到包裝的:

import scala.reflect.runtime.universe._ 

object ScalaApplication { 
    def main(args: Array[String]) { 
    val anyWrapper = new AnyWrapper 

    List(1,2,3).foreach { i => 
     i match { 
     case 1 => anyWrapper.any = 42 
     case 2 => anyWrapper.any = "a string" 
     case 3 => anyWrapper.any = true 
     } 
     print(anyWrapper.any) 
     print(" has type ") 
     println(anyWrapper.typeOfAny) 
    } 
    } 

    class AnyWrapper { 
    private var _any: Any = null 
    private var _typeOfAny: Type = null 

    def any = _any 
    def typeOfAny = _typeOfAny 
    def any_=[T: TypeTag](a: T) = { 
     _typeOfAny = typeOf[T] 
     _any = a 
    } 

    } 
} 

這應該給輸出:

$ scala ScalaApplication.scala 
42 has type Int 
a string has type String 
true has type Boolean 

但是這種解決方案仍然不包括在編譯時引用類型未知的情況。

[更新2:]

如果類型是顯式轉換爲Any類型的引用,你可能要列舉所有可能的類型在比賽中聲明,以恢復類型:

import scala.reflect.runtime.universe._ 

object ScalaApplication { 
    def main(args: Array[String]) { 

    List(1,2,3).foreach { i => 
     val any: Any = i match { 
     case 1 => 42.asInstanceOf[Any] 
     case 2 => "a string".asInstanceOf[Any] 
     case 3 => true.asInstanceOf[Any] 
     } 
     print(any) 
     print(" has type ") 
     println(matchType(any)) 
    } 
    } 

    def matchType(any: Any) = { 
    any match { 
     case a: Int => typeOf[Int] 
     case a: String => typeOf[String] 
     case a: Boolean => typeOf[Boolean] 
    } 
    } 
} 

這應該給輸出:

$ scala ScalaApplication.scala 
42 has type Int 
a string has type String 
true has type Boolean 

但是這種解決方案需要你知道(一nd列表)您可以在any值中收到的所有可能類型。

+0

此解決方案只適用於類型是在編譯時已知。 這裏的打印類型的用於該值未在編譯時已知的對象上的結果: 階> VAL X:任何=列表(42) X:任何=列表(42) 階>打印類型(X ) 任何 –

+0

從你原來的問題中,我認爲你特別想在運行時獲得類型參數,例如'List(42)',其中類型參數只是沒有明確給出。 –

+0

我用一個可能更接近你需要的包裝的例子更新了我的答案。這樣的包裝會解決你的問題嗎? –

相關問題