2010-10-29 11 views
6

Considerando il seguente frammento di codice Scala:`productElement (i)` su una classe di case usa la riflessione?

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

Fa l'invocazione di inspect() qui significa che la riflessione è utilizzato (in qualsiasi modo)?

Mi piacerebbe in qualche modo poter accedere ai campi di una case-class senza doverli fare esplicitamente riferimento, ad es. da foo.v1 e preferirei una soluzione che non richiede riflessione poiché mi aspetto che comporti un sovraccarico.

risposta

11

Nessun riflesso verrà utilizzato per il prodotto Elemento. È un trucco per compilatore. Aggiungendo il caso prima che una classe non crei solo un oggetto associato (con metodo apply e così via, vedere http://www.scala-lang.org/node/258), estende anche la classe dal prodotto tratto. Il compilatore crea le implementazioni dei metodi astratti productArity e productElement.

L'uscita del scalac -print Foo.scala lo mostra:

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

Se si desidera accedere ai campi senza riflessione, è possibile utilizzare il metodo productElement dalla caratteristica del prodotto

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

Grande risposta! Inoltre, l'opzione '-print' sembra molto utile e fino ad ora non ne sapevo nulla. Grazie Steve! –

Problemi correlati