2013-08-04 6 views
11

Mi piacerebbe avere un metodo comeCome posso ottenere Class [T] da un ClassTag [T] implicito?

def retrieve[T](value: Option[T])(implicit ct: ClassTag[T]): T; 

All'interno di questo metodo che ho bisogno di chiamare un metodo Java (al di là del mio controllo) per creare un'istanza di T che richiede Class[T]:

public <T> T construct(clazz: Class<T> /* other arguments */) { ... } 

Come posso ottenere Class[T] da ClassTag[T]? Per prima cosa ho pensato che potrei usare runtimeClass da ClassTag, ma il suo tipo è Class[_], non Class[T]. O c'è qualche altro valore implicito che il compilatore può fornire automaticamente, dal quale posso ottenere Class[T]?

+6

Non si deve aver paura di getto quando si usa Java riflessione. Basta fare 'asInstanceOf [Class [T]]'. –

risposta

14

Here is the ticket sul getClass e la linked forum discussion in cui Odersky specula:

Si potrebbe anche usare un cast.

Here is the duplicate ticket dove getClass è stato risolto. 5.getClass calchi anche:

/** Return the class object representing an unboxed value type, 
* e.g. classOf[int], not classOf[java.lang.Integer]. The compiler 
* rewrites expressions like 5.getClass to come here. 
*/ 
def anyValClass[T <: AnyVal : ClassTag](value: T): jClass[T] = 
    classTag[T].runtimeClass.asInstanceOf[jClass[T]] 

La limitazione è che ricorda this question about pattern matching con ClassTag, in cui le nostre aspettative ingenue sono, inoltre, non soddisfatte.

La resistenza a Class[A] rappresenta il disadattamento di impedenza tra i tipi Scala e la piattaforma?

Dato il tipo di classe, tutto ciò che si può veramente fare è newInstance. Ma l'invocazione riflessiva con uno specchio costruttore non mi restituirà il mio tipo.

scala> res24 reflectConstructor res25.asMethod 
res27: reflect.runtime.universe.MethodMirror = constructor mirror for Bar.<init>(): Bar (bound to null) 

scala> res27() 
res28: Any = [email protected] 

scala> bar.getClass.newInstance 
res29: Bar = [email protected] 

scala> classOf[Bar].newInstance 
res30: Bar = [email protected] 

Non sembra giusto.

Come conclude il thread di posta elettronica del 2008, si prevede di utilizzare un numero inferiore di cast in Scala.

BTW, non è che mi rifiutavo di crederci il codice commento, ma:

scala> 5.getClass 
res38: Class[Int] = int 

scala> :javap - 
    Size 1285 bytes 
    MD5 checksum a30a28543087238b563fb1983d7d139b 
    Compiled from "<console>" 

[snip]

9: getstatic  #27     // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$; 
12: iconst_5  
13: invokestatic #33     // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; 
16: getstatic  #38     // Field scala/reflect/ClassTag$.MODULE$:Lscala/reflect/ClassTag$; 
19: invokevirtual #42     // Method scala/reflect/ClassTag$.Int:()Lscala/reflect/ClassTag; 
22: invokevirtual #46     // Method scala/runtime/ScalaRunTime$.anyValClass:(Ljava/lang/Object;Lscala/reflect/ClassTag;)Ljava/lang/Class; 
25: putfield  #18     // Field res38:Ljava/lang/Class; 
28: return   
+0

È una buona ricerca, ma non una buona risposta. Collegamenti, citazioni, codice sorgente, disassemblaggio ... Quindi come faccio a ottenere una 'Classe [T]' da un 'ClassTag [T]'? (Voglio dire che posso capirlo, ma penso che la prima priorità della risposta dovrebbe essere quella di rispondere a questa domanda e solo successivamente fornire il contesto.) –

+1

@DanielDarabos dice che usa un cast e poi mostra un esempio usando un cast per andare da ClassTag alla classe. Questa risposta va ben oltre la chiamata del dovere. Il PO non aveva un'opinione. –

+0

_ "Usa un cast" _ è una citazione di una speculazione da un forum. L '"esempio" è uno snippet di codice proveniente dagli interni di runtime di Scala ('ScalaRunTime.scala') e viene inserito senza dire" questo è come lo si fa ". Restituisce un 'jClass [T]', che è un alias locale per 'Classe [T]' nel file, ma i lettori della risposta non lo sanno. Ad ogni modo, non voglio criticare la risposta, volevo solo dare un feedback. È una risposta molto perspicace a prescindere. –