Runtime resolution of type arguments using scala 2.10 reflection

后端 未结 1 1900
暗喜
暗喜 2021-01-05 10:52

Given a type declaration, I am able to resolve the type argument.

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


        
相关标签:
1条回答
  • 2021-01-05 11:18

    An example based on TypeTag knowledge gained from reading Scala: What is a TypeTag and how do I use it? posted by Eugene Burmako in the comments on your question:

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

    This should give the output:

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

    [UPDATE 1:]

    However, if you want to be aware of the type assigned to a reference of type Any you might have to opt for some sort of type aware wrapper:

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

    This should give the output:

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

    But this solution still does not cover the case where the reference type is unknown at compile time.

    [UPDATE 2:]

    If the types are explicitly cast to reference of type Any, you might have to enumerate all the possible types in a match statement in order to recover the type:

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

    This should give the output:

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

    But this solution requires you to know (and list) all the possible types that you could receive in the any value.

    0 讨论(0)
提交回复
热议问题