当超类中存在具有相同类型的隐式 val 时,编译器不会为隐式 val 生成字段

Compiler doesn't generate a field for implicit val when an implicit val with the same type is present in the superclass

我有一个classFoo定义如下:

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]

令我惊讶的是,getDeclaredFields 包括 eA:

object Test extends App {
  private val fields = classOf[Foo[_, _]].getDeclaredFields

  println(fields.mkString("\n"))
  assert(fields.exists(_.getName == "eA"))
}

产生

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(JNIExtractorOps.scala:15)
    at scalan.Test$delayedInit$body.apply(JNIExtractorOps.scala:11)

是否有对此的解释或者这是一个已知错误(Scala 版本是 2.11.7)?我 可以 从 class.

外部访问 eA

似乎编译器决定它可以为 eA 重用 selfType 字段,如果它不中断在 scala-reflect 中对 eA 的访问,那就太好了。

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.