2 votes

la réflexion scala ne peut pas fonctionner dans ce cas

J'ai déclaré une classe :

trait TO {  
    @BeanProperty var id: String = _ 
    @BeanProperty var age : Int = _     
    @BeanProperty var createdAt : Long = _ 
    @BeanProperty var disable: Boolean = _ 
}
class UMTTestObject extends TO {
    @BeanProperty var inner: UMTInnerTO = _
}
class UMTInnerTO extends TO{}

Et dans la réflexion, cela ne fonctionne pas pour setAge de UMTInnerObject :

setter.invoke(inner, 0)

alors que setter est setAge de UMTInnerObject, inner est une instance de UMTInnerObject

Le message d'erreur s'affiche :

java.lang.NoSuchMethodError : me.baihe.blackhole.luna.helpers.TO$class.setAge(Lme/baihe/blackhole/luna/helpers/TO;I)V

C'est très énigmatique

Quelqu'un sait pourquoi ?

2voto

jeslg Points 629

Cette session REPL montre comment vous pouvez invoquer le setter avec l'API Reflection de Scala :

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

scala> trait TO { var age: Int = _ }
defined trait TO

scala> class UMTInnerTO extends TO
defined class UMTInnerTO

scala> val inner = new UMTInnerTO
inner: UMTInnerTO = UMTInnerTO@173379f

scala> val m = ru.runtimeMirror(inner.getClass.getClassLoader)
m: reflect.runtime.universe.Mirror ...

scala> val im = m.reflect(inner)
im: reflect.runtime.universe.InstanceMirror = instance mirror for UMTInnerTO@173379f

scala> val setterSymb = (ru.typeOf[UMTInnerTO].members find (_.name.decoded == "age_=")).get
setterSymb: reflect.runtime.universe.Symbol = method age_=

scala> val setter = im.reflectMethod(setterSymb.asMethod)
setter: reflect.runtime.universe.MethodMirror = method mirror for TO.age_$eq(x$1: scala.Int): scala.Unit (bound to UMTInnerTO@173379f)

scala> inner.age
res0: Int = 0

scala> setter(5)
res1: Any = ()

scala> inner.age
res2: Int = 5

Vous pouvez visiter le Documentation de Scala Reflection pour comprendre ce qui se passe dans le snippet.

--

MISE À JOUR : Quoi qu'il en soit, si vous êtes toujours intéressé par l'API Java, c'est parti !

Vous devez savoir que setters en Scala n'utilisent pas la convention de dénomination Java. Vous ne trouverez pas de setAge (du moins, si vous ne la déclarez pas manuellement). Au lieu de cela, vous devez rechercher un age_= méthode.

scala> classOf[UMTInnerTO].getMethod("age_$eq", classOf[Int])
res0: java.lang.reflect.Method = public void UMTInnerTO.age_$eq(int)

scala> inner.age
res1: Int = 0

scala> res0.invoke(inner, 3: Integer)
res2: Object = null

scala> inner.age
res3: Int = 3

Ce site poste sur les getters et setters pourrait être utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X