2016-09-08 4 views
0

Ich frage mich, ob es Art und Weise ist es, den deklarierten Typen in dem zugrundeliegenden Iterable zu erhalten, wie in:Wie wird der Typ von Iterable in Scala deklariert?

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 

ich die Klasse dieser Typen wissen müssen, so kann ich die zugrunde liegende Json-Bibliothek verwenden, um den JSON-String deserialisieren in diesen Typ.

So etwas wie

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

Dank

Antwort

0

Ich habe vielleicht nicht genügend Informationen in meiner Frage zur Verfügung gestellt. Wie auch immer, ich habe die Antwort gefunden.

Um eine Klasse von einer generischen Art abzurufen hatte ich folgenden

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 

ich diese Klasse auf die zugrunde liegende Bibliothek zur Verfügung stellen kann dann zu tun, seine Arbeit zu tun. Danke

0
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$1: 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 
+0

Danke Sarvesh für das oben genannte. Ich denke, was ich brauche, um Zugang zu bekommen, ist A.getClass, zum Beispiel List [Person], dann müsste ich wissen, dass es eine Person ist, damit ich Person.getClass aufrufen kann. Dies ist für die zugrunde liegende Bibliothek wie Jackson ObjectMapper, die Reflexion verwendet bereitzustellen. Könnte eine andere Möglichkeit sein, meine Methode zu definieren, um die Klasse zu übernehmen, zB Def von Json (jsonString: String, class: Class) Ich versuchte das zu vermeiden. –

Verwandte Themen