如何在 Scala 中获取从 Iterable 声明的类型?

How to get type declared from Iterable in Scala?

我想知道是否有办法在底层 Iterable 中获取声明的类型,如:

var string: Seq[String] => I want something to return String 
var int: Seq[Int] = _ => I want something to return Int
var genericType: Seq[A] => I want to return A

我需要知道这些类型的 class 以便我可以使用底层 Json 库将 json 字符串反序列化为这种类型。

类似于

def fromJson[A](jsonString: String)(implicit tag: TypeTag[A]): A =  ???

谢谢

scala> class A(i: Int) {
 | override def toString = "A("+i+")"
 | }
defined class A

scala> class B(i: Int) extends A(i) {
 | override def toString = "B("+i+")"
 | }
defined class B

scala> val list: List[A] = List(new A(1), new B(2), new B(3), new A(4))
list: List[A] = List(A(1), B(2), B(3), A(4)) 

// if you just want the name of class

// full class name with package info
scala> val fullClassNameList = list.map(s => s.getClass.getName)
fullClassNameList: List[String] = List(A, B, B, A)


// If you want the actual runtime Type

scala> import scala.reflect.runtime.{universe=>ru}
import scala.reflect.runtime.{universe=>ru}

scala> def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
getTypeTag: [T](obj: T)(implicit evidence: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.TypeTag[T]

// if you just wanted to find the Type parameter of the List,

// get TypeTag of list
val listTypeTag = getTypeTag(list)
listTypeTag: reflect.runtime.universe.TypeTag[List[A]] = TypeTag[scala.List[A]]

// get Type of list
scala> val listType = listTypeTag.tpe
listType: reflect.runtime.universe.Type = scala.List[A]

// get TypeArgs of the Type of list
scala> val listTypeArgs = listType.typeArgs
listTypeArgs: List[reflect.runtime.universe.Type] = List(A)

// Now, we know that List[A] takes just 1 type parameter
// that is the type we are looking for
scala> val theTypeOfList = listTypeArgs.head
theTypeOfList: reflect.runtime.universe.Type = A

我的问题可能没有提供足够的信息。不管怎样,我找到了答案。

为了从通用类型中检索 class,我必须执行以下操作

import scala.reflect.runtime.universe._
val m = runtimeMirror(getClass.getClassLoader)
def myMethod[A](implicit t: TypeTag[A]) = {
  val aType = typeOf[A]
  aType.typeArgs match {
     case x: List[_] if x.nonEmpty => m.runtimeClass(x.head)
     case x: List[_] if x.isEmpty => m.runtimeClass(aType)
  }
}
scala> myMethod[Seq[String]]
res3: Class[_] = class java.lang.String

scala> myMethod[Seq[Int]]
res4: Class[_] = int

scala> case class Person(name: String)
defined class Person

scala> myMethod[Seq[Person]]
res5: Class[_] = class Person

scala> myMethod[Person]
res6: Class[_] = class Person

然后我可以将这个 class 提供给底层库来完成它的工作。 谢谢