Использует ли `productElement (i)` для класса наблюдений отражение? - PullRequest
6 голосов
/ 29 октября 2010

Учитывая следующий фрагмент 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(), что отражение используется (каким-либо образом)?

Я бы хотел как-то бытьвозможность доступа к полям класса case без явной ссылки на них, например, foo.v1, и я предпочел бы решение, которое не требует отражения, поскольку я ожидаю, что оно повлечет за собой некоторые накладные расходы.

1 Ответ

11 голосов
/ 29 октября 2010

Для productElement не будет использоваться отражение. Это трюк с компилятором. Добавление case до того, как класс не просто создает сопутствующий объект (с методом 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 из признака Product

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