2010-10-29 12 views
6

Teniendo en cuenta el siguiente fragmento de Scala:¿`productoElemento (i)` en una clase de caso utiliza reflexión?

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

¿La invocación de inspect() aquí significa que la reflexión se utiliza (en cualquier forma)?

Me gustaría de alguna manera poder acceder a los campos de una clase de caso sin tener que referirme explícitamente a ellos, p. Ej. por foo.v1 y yo preferiría una solución que no requiera reflexión, ya que supongo que implica un cierto gasto.

Respuesta

11

Sin reflexionar se utilizará para el productoElement. Es un truco de compilación. Agregar mayúsculas/minúsculas antes de una clase no solo crea un objeto complementario (con el método apply, etc., consulte http://www.scala-lang.org/node/258), sino que también extiende la clase desde el producto de rasgo. El compilador crea implementaciones de los métodos abstractos productArity y productElement.

La salida de scalac -print Foo.scala muestra que:

... 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 desea acceder a los campos sin reflexión, puede utilizar el método de la productElement rasgo Producto

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

Gran respuesta! Además, la opción '-print' parece bastante útil y hasta ahora no sabía nada al respecto. Gracias Steve! –

Cuestiones relacionadas