2010-10-29 27 views
6

Vu l'extrait Scala suivant:Est-ce que `productElement (i)` sur une classe de cas utilise la réflexion?

case class Foo(v1: String, v2: Int, v3: Any) 

def inspect(p: Product) = 
    (0 until p.productArity).foreach(i => println(p.productElement(i))) 

inspect(Foo("Moin", 77, null)) 

Est-ce que l'invocation de inspect() signifie ici que la réflexion est utilisé (de quelque manière)? J'aimerais pouvoir accéder d'une manière ou d'une autre aux champs d'une classe de cas sans devoir y faire explicitement référence, par ex. par foo.v1 et je serais favorable à une solution qui ne nécessite pas de réflexion puisque je m'attends à ce que cela entraîne des frais généraux.

Répondre

11

Aucune réflexion ne sera utilisée pour l'élément productElement. C'est un truc de compilateur. Ajouter un cas avant une classe ne crée pas seulement un objet compagnon (avec la méthode apply et ainsi de suite, voir http://www.scala-lang.org/node/258), il étend également la classe à partir du trait Produit. Le compilateur crée des implémentations des méthodes abstraites productArity et productElement.

La sortie de scalac -print Foo.scala le montre:

... case class Foo extends java.lang.Object with ScalaObject with Product { 
... 
override def productArity(): Int = 3; 
override def productElement(x$1: Int): java.lang.Object = { 
    <synthetic> val temp6: Int = x$1; 
    (temp6: Int) match { 
    case 0 => { 
     Foo.this.v1() 
    } 
    case 1 => { 
     scala.Int.box(Foo.this.v2()) 
    } 
    case 2 => { 
     Foo.this.v3() 
    } 
    case _ => { 
     throw new java.lang.IndexOutOfBoundsException(scala.Int.box(x$1).toString()) 
    } 
    } 
}; 
... 
} 

Si vous souhaitez accéder aux champs sans réflexion, vous pouvez utiliser la méthode productElement du trait produit

scala> case class Foo(v1: String, v2: Int, v3: Any) 
defined class Foo 

scala> val bar = Foo("Moin", 77, null) 
bar: Foo = Foo(Moin,77,null) 

scala> bar.productElement(0) 
res4: Any = Moin 

scala> bar.productElement(1) 
res5: Any = 77 

scala> bar.productElement(2) 
res6: Any = null 
+0

de Grande réponse! De plus, l'option '-print' semble assez utile et je ne l'ai pas encore connue. Merci Steve! –