Tom
Tom

Reputation: 6332

How to figure out the type parameter for nested type parameter

With the following code,new Box(10), new Box("20") works well for me. But for the new Box(Seq(20)), new Box(Seq("20"))), I would like to figure out the type of type parameter for the Seq, so that I could print Seq[Int], Seq[String]

      @Test
      def testClassTag(): Unit = {
        class Box[T:ClassTag](val data: T) {
          def printTypeParameter() = {
            val tag = implicitly[ClassTag[T]].runtimeClass
            tag match {
              case _ if tag == classOf[Int] => println("Int")
              case _ if tag == classOf[String] => println("String")
              case _ if tag == classOf[Seq[_]] => println( "Seq")
            }
          }
        }
        val boxes = Seq(new Box(10),  new Box("20"), new Box(Seq(20)), new Box(Seq("20")))
        boxes.foreach(_.printTypeParameter())

  }

Upvotes: 0

Views: 152

Answers (2)

Tom
Tom

Reputation: 6332

@dima's answer is elegant, I would put another way that detects the type parameter step by step.

 @Test
  def testTypeTag1(): Unit = {
    class Box[T: TypeTag](val data: T) {
      def printTypeParameter() = {
        typeOf[T] match {
          case t if t =:= typeOf[Int] => println("Int")
          case t if t =:= typeOf[String] => println("String")
          case t if t <:< typeOf[Seq[Any]] => {
            val TypeRef(_, _, Seq(elementType)) =  typeOf[T]
            elementType match {
              case t if t =:= typeOf[Int] =>println("Seq[Int]")
              case t if t =:= typeOf[String] =>println("Seq[String]")
              case _=>println("Seq[Unknown]")
            }
          }
          case _ => println("Unknown")
        }
      }
    }
    val boxes = Seq(new Box(10), new Box("20"), new Box(Seq(20)), new Box(Seq("20")))
    boxes.foreach(_.printTypeParameter())
  }

Upvotes: 1

Dima
Dima

Reputation: 40500

The new proper way to do it is using TypeTag instead of ClassTag:

def foo[T : TypeTag](data: T) = typeOf[T] match {
  case t if t =:= typeOf[Int] => println("Int")
  case t if t =:= typeOf[String] => println("String")
  case t if t <:< typeOf[Seq[String]] => println("Seq[String]")
  // etc
}

(If you just want to print it out, you can as well do this:

def foo[T : TypeTag](data: T) = println(typeOf[T])`

it does the same thing, but handles all types, not just the ones you could think of.

Upvotes: 2

Related Questions