如何在 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 提供给底层库来完成它的工作。
谢谢
我想知道是否有办法在底层 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 提供给底层库来完成它的工作。 谢谢