Задать вопрос

Вопрос по Scala (2.10.x) и reflection — как отличить аргументы первичного конструктора от «полей»

Есть класс B наследующийся от класса A:

class A(val aparam: String) {...}

class B(bparam: String) extends A(bparam) {
    var someb1 = "somevalue"
    val someb2 = "somevalue"
}

Если с помощью reflection исследовать класс B:

val b = new B("hello")

val mirror = runtimeMirror(b.getClass.getClassLoader)
val alltypes = mirror.reflect(b).symbol.typeSignature.baseClasses.filter(c => c.isClass).map(c => c.asClass.typeSignature)

val vars: Seq[TermSymbol] = alltypes.flatMap(t => t.members.filter(m => m.isTerm && (m.asTerm.isVal || m.asTerm.isVar)).map(x => x.asTerm))

И вывести «vars», то выдастся что-то вида:

value aparam
value bparam
variable someb1
value someb2


Т.е. выдаются и аргументы первичного конструктора (bparam)

Вопрос: Как различить аргументы первичного конструктора от «полей», т.е.
хочется игнорировать bparam и не игнорировать aparam (метод isParamAccessor
выдаст true для aparam и bparam)?

Если в дальнейшем попытаться получить значение bparam через reflection
(например так: vars.map(v => mirror.reflect(b).reflectField(v).get), то выпадет исключение:

scala.ScalaReflectionException: Scala field aparam isn't represented as a Java
field, neither it has a Java accessor method note that private parameters of
class constructors don't get mapped onto fields and/or accessors, unless they
are used outside of their declaring constructors.

О котором и предупреждают в scaladoc к reflectField:
If a field symbol doesn't correspond to a reflectable entity of the underlying
platform, a ScalaReflectionException exception will be thrown. This might
happen, for example, for primary constructor parameters. Typically they produce
class fields, however, private parameters that aren't used outside the
constructor remain plain parameters of a constructor method of the class.
  • Вопрос задан
  • 3149 просмотров
Подписаться 3 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 1
Ojow
@Ojow
Так подойдёт?

Welcome to Scala version 2.10.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_41).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class A(val aparam: String)
defined class A

scala> class B(bparam: String) extends A(bparam)
defined class B

scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}

scala> ru.typeTag[B].tpe.declarations
res3: reflect.runtime.universe.MemberScope = SynchronizedOps(value bparam, constructor B)

Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы