2012-09-17 13 views
7

Data una dichiarazione di tipo, sono in grado di risolvere l'argomento type.Risoluzione runtime degli argomenti di tipo utilizzando la riflessione di scala 2.10

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

Per un valore di runtime, lo stesso metodo non funziona.

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

C'è un modo per superare il tipo di cancellazione per i valori riflessi?

+0

Forse è possibile trovare una valida soluzione dopo aver letto [questa risposta] (http://stackoverflow.com/a/1094214/315306) – Raffaele

+0

@Raffaele. Grazie per il riferimento Sfortunatamente la domanda (e la risposta) trattano il caso quando i tipi sono concreti e sono noti durante il tempo di compilazione. I manifesti sono ora deprecati e TypeTags (che ha sostituito i manifesti) richiedono tag concreti. –

+1

Utilizzare AbsTypeTag (in RC1 rinominato in WeakTypeTag). Maggiori informazioni qui: http://stackoverflow.com/questions/12218641/scala-2-10-what-is-a-typetag-and-how-do-i-use-it –

risposta

6

Un esempio basato sulla conoscenza typetag acquisite dalla lettura Scala: What is a TypeTag and how do I use it? pubblicato da Eugene Burmako in sede di commento alla tua domanda:

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]) 
    } 
} 

questo dovrebbe dare l'output:

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

[UPDATE 1:]

Tuttavia, se si vuole essere consapevoli del tipo assegnato ad un riferimento di tipo Any potrebbe essere necessario optare per una sorta di tipo di involucro a conoscenza:

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 
    } 

    } 
} 

Questo dovrebbe dare l'output:

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

Ma questa soluzione non copre ancora il caso in cui il tipo di riferimento è sconosciuto al momento della compilazione.

[UPDATE 2:]

Se i tipi sono esplicitamente espressi al riferimento di tipo Any, potrebbe essere necessario enumerare tutti i possibili tipi in una dichiarazione partita al fine di recuperare il tipo:

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] 
    } 
    } 
} 

questo dovrebbe dare l'output:

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

Ma questa soluzione richiede che tu sappia (un nd elenco) tutti i tipi possibili che è possibile ricevere nel valore any.

+0

Questa soluzione funziona solo quando il tipo è noto in fase di compilazione. Ecco un risultato di PrintType su un oggetto il cui valore non è noto in fase di compilazione: scala> val x: Qualsiasi List = (42) x: Qualunque = Lista (42) scala> PrintType (x Qualsiasi –

+0

Dalla tua domanda iniziale ho pensato che volevi essere in grado di ottenere parametri di tipo in fase di esecuzione per cose come 'List (42)' dove il tipo args non è dato esplicitamente. –

+0

Ho aggiornato la mia risposta con un esempio di un wrapper che potrebbe essere più vicino a quello che ti serve. Un involucro del genere risolverebbe il tuo problema? –

Problemi correlati