Scala équivalent de l'objet Java java.lang.Class <T>

183

La question est mieux expliquée par un exemple:

Dans Java pour un EntityManager JPA, je peux faire ce qui suit (le compte est ma classe d'entité):

Account result = manager.find(Account.class, primaryKey);

Dans Scala, ma tentative naïve est:

val result = manager.find(Account.class, primaryKey)

Mais quand j'essaye d'utiliser Account.classScala, ça ne semble pas aimer ça. Comment puis-je spécifier l'objet java.lang.Class pour la classe Account dans Scala?

Kekoa
la source
VonC a déjà fourni la réponse, mais jetez un œil à ma propre question / réponse sur Scala & Erasure. Je pense que cela pourrait vous donner des idées pour faire les choses d'une manière différente de ce que vous essayez.
Daniel C.Sobral

Réponses:

264

Selon " The Scala Type System ",

val c = new C
val clazz = c.getClass              // method from java.lang.Object
val clazz2 = classOf[C]             // Scala method: classOf[C] ~ C.class
val methods = clazz.getMethods      // method from java.lang.Class<T>

La classOf[T]méthode retourne la représentation d'exécution pour un type Scala. C'est analogue à l'expression Java T.class.
L'utilisation classOf[T]est pratique lorsque vous avez un type sur lequel vous souhaitez obtenir des informations, tandis qu'elle getClassest pratique pour récupérer les mêmes informations à partir d'une instance du type.

Cependant, classOf[T]et getClassrenvoie des valeurs légèrement différentes, reflétant l'effet de l'effacement de type sur la JVM, dans le cas de getClass.

scala> classOf[C]
res0: java.lang.Class[C] = class C

scala> c.getClass
res1: java.lang.Class[_] = class C

C'est pourquoi ce qui suit ne fonctionnera pas :

val xClass: Class[X] = new X().getClass //it returns Class[_], nor Class[X]

val integerClass: Class[Integer] = new Integer(5).getClass //similar error

Il existe un ticket concernant le type de retour degetClass .

( James Moore rapporte que le ticket est "maintenant", c'est-à-dire novembre 2011, deux ans plus tard, corrigé.
En 2.9.1, fait getClassmaintenant:

scala> "foo".getClass 
       res0: java.lang.Class[_ <: java.lang.String] = class java.lang.String

)

De retour en 2009:

Ce serait utile si Scala traitait le retour de getClass () comme un java.lang.Class [T] forSome {val T: C} où C est quelque chose comme l'effacement du type statique de l'expression sur laquelle getClass est appelé

Cela me permettrait de faire quelque chose comme ce qui suit où je veux introspecter une classe mais ne devrait pas avoir besoin d'une instance de classe.
Je souhaite également limiter les types de classes sur lesquelles je souhaite effectuer une introspection, j'utilise donc Class [_ <: Foo]. Mais cela m'empêche de passer dans une classe Foo en utilisant Foo.getClass () sans cast.

Remarque: concernant getClass, une solution de contournement possible serait:

class NiceObject[T <: AnyRef](x : T) {
  def niceClass : Class[_ <: T] = x.getClass.asInstanceOf[Class[T]]
}

implicit def toNiceObject[T <: AnyRef](x : T) = new NiceObject(x)

scala> "Hello world".niceClass                                       
res11: java.lang.Class[_ <: java.lang.String] = class java.lang.String
VonC
la source
4
Pour info, le ticket @VonC mentionné a été marqué comme fixe le 22 / juin / 11. Dans la version 2.9.1, getClass fait maintenant: scala> "foo" .getClass res0: java.lang.Class [_ <: java.lang.String] = class java.lang.String
James Moore
49

classOf[Account]en Scala équivaut à Account.classen Java.

Jonathan Graehl
la source