I have a class Foo
defined as follows:
class Elem[A]
abstract class BaseDef[T](implicit val selfType: Elem[T])
case class Foo[A, T]()(implicit val eA: Elem[A], val eT: Elem[T]) extends BaseDef[A]
To my surprise, getDeclaredFields
does not include eA
:
object Test extends App {
private val fields = classOf[Foo[_, _]].getDeclaredFields
println(fields.mkString("\n"))
assert(fields.exists(_.getName == "eA"))
}
produces
private final scalan.Elem scalan.Foo.eT
Exception in thread "main"
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:151)
at scalan.Test$.delayedEndpoint$scalan$Test$1(JNIExtractorOps.scala:15)
at scalan.Test$delayedInit$body.apply(JNIExtractorOps.scala:11)
Is there an explanation for this or is this a known bug (Scala version is 2.11.7)? I can access eA
from outside the class.
It seems the compiler decides it can reuse selfType
field for eA
, which would be great if it didn't break access to eA
in scala-reflect.
Reply from Jason Zaugg on scala-user:
The compiler avoids redundant fields in subclasses if it statically determines that the value is stored in a field in a super class that exposes it via an accessible accessor.
To prevent this, you might be able to change the superclass constructor by removing the val keyword and add another val to that class that stores the parameter.