2010-10-29 53 views
6

考慮下面的Scala代碼片段:caseElass(i)`case-class是否使用反射?

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和我喜歡的解決方案,不需要反思,因爲我期望它會帶來一些開銷。

回答

11

沒有反射將用於productElement。這是一個編譯器技巧。在類之前添加案例不僅僅是創建伴隨對象(使用apply方法等,請參閱http://www.scala-lang.org/node/258),它還從特質Product擴展了類。編譯器創建抽象方法productArity和productElement的實現。

scalac -print Foo.scala輸出顯示它:

... 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, 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

偉大的答案!而且,'-print'選項看起來非常有用,至今我都不知道。謝謝史蒂夫! – 2010-10-30 08:27:57