考虑以下
Scala片段:
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))
在这里调用inspect()是否意味着使用反射(以任何方式)?
我想以某种方式能够访问案例类的字段而不必明确地引用它们,例如通过foo.v1,我赞成一个不需要反射的解决方案,因为我希望它需要一些开销.
解决方法
productElement不会使用反射.这是一个编译技巧.在类之前添加大小写不只是创建一个伴随对象(使用apply方法等,参见
http://www.scala-lang.org/node/258),它还从特征Product扩展了类.编译器创建抽象方法productArity和productElement的实现.
... 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()) } } }; ... }
如果要访问没有反射的字段,可以使用特征产品中的方法productElement
scala> case class Foo(v1: String,v3: Any) defined class Foo scala> val bar = Foo("Moin",null) bar: Foo = Foo(Moin,null) scala> bar.productElement(0) res4: Any = Moin scala> bar.productElement(1) res5: Any = 77 scala> bar.productElement(2) res6: Any = null