2012-09-17 26 views
7

Dada una declaración de tipo, puedo resolver el argumento de tipo.Resolución de tiempo de ejecución de los argumentos de tipo usando la reflexión de scala 2.10

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

Para un valor de tiempo de ejecución, el mismo método no funciona.

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

¿Hay alguna manera de superar el borrado de tipo para los valores reflejados?

+0

Quizás pueda encontrar una solución viable después de leer [esta respuesta] (http://stackoverflow.com/a/1094214/315306) – Raffaele

+0

@Raffaele. Gracias por la referencia. Lamentablemente, la pregunta (y la respuesta) tratan el caso cuando los tipos son concretos y se conocen durante el tiempo de compilación. Los manifiestos ahora están en desuso, y los tipos de etiquetas (que reemplazan los manifiestos) requieren etiquetas concretas. –

+1

Utilice AbsTypeTag (en RC1 renombrado a WeakTypeTag). Más información aquí: http://stackoverflow.com/questions/12218641/scala-2-10-what-is-a-typetag-and-how-do-i-use-it –

Respuesta

6

Un ejemplo basado en el conocimiento TypeTag adquirida con la lectura de Scala: What is a TypeTag and how do I use it? Publicado por Eugene Burmako en los comentarios sobre su pregunta:

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

Esto debería dar la salida:

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

[ACTUALIZACIÓN 1:]

Sin embargo, si quieres estar al tanto de tipo asignado a una referencia de tipo Any puede que tenga que optar por algún tipo de tipo de envoltorio en cuenta:

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 
    } 

    } 
} 

Esto debería dar la salida:

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

Pero esta solución aún no cubre el caso donde el tipo de referencia es desconocido en tiempo de compilación.

[ACTUALIZACIÓN 2:]

Si los tipos son emitidos de forma explícita a la referencia del tipo Any, usted podría tener que enumerar todos los tipos posibles en un comunicado partido con el fin de recuperar el 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] 
    } 
    } 
} 

esto debería dar la salida:

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

Pero esta solución requiere que sepas (una nd list) todos los tipos posibles que podría recibir en el valor any.

+0

Esta solución funciona solo cuando el tipo es conocido en tiempo de compilación. Así es resultado de TipoImpresión en un objeto para el que el valor no es conocido en tiempo de compilación: Scala> val x: cualquier lista = (42) x: Cualquier = Lista (42) Scala> TipoImpresión (x) Cualquiera –

+0

De su pregunta original, pensé que específicamente deseaba obtener parámetros de tipo en tiempo de ejecución para cosas como 'List (42)' donde los tipos args simplemente no se dan explícitamente. –

+0

He actualizado mi respuesta con un ejemplo de un contenedor que podría estar más cerca de lo que necesita. ¿Tal envoltorio resolvería su problema? –

Cuestiones relacionadas