2010-10-29 11 views
6

Unter Berücksichtigung der folgenden Scala Schnipsel:Verwendet `productElement (i)` auf einer Fallklasse Reflektion?

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)) 

Ist der Aufruf von inspect() bedeutet hier, daß die Reflexion (in welcher Weise auch immer) wird verwendet?

Ich möchte irgendwie auf die Felder einer Fallklasse zugreifen können, ohne sich explizit auf sie beziehen zu müssen, z.B. von foo.v1 und ich würde eine Lösung bevorzugen, die keine Reflexion erfordert, da ich erwarte, dass es einige Overhead mit sich bringt.

Antwort

11

Für das productElement wird keine Reflexion verwendet. Es ist ein Compiler-Trick. Durch das Hinzufügen von Groß-/Kleinschreibung vor einer Klasse wird nicht nur ein Begleitobjekt erstellt (mit der Methode apply usw., siehe http://www.scala-lang.org/node/258), sondern auch die Klasse aus dem Merkmal Produkt erweitert. Der Compiler erstellt Implementierungen der abstrakten Methoden productArity und productElement.

Die Ausgabe von scalac -print Foo.scala zeigt es:

... 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()) 
    } 
    } 
}; 
... 
} 

Wenn Sie auf die Felder ohne Reflexion zugreifen möchten, können Sie die Methode productElement aus dem Merkmal Produkt

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

Große Antwort verwenden können! Außerdem scheint die '-print'-Option recht nützlich zu sein und ich wusste bisher nichts davon. Danke Steve! –

Verwandte Themen