親トレイトで定義されている val を、子トレイトで override するとインスタンス化に失敗する

子側のトレイトで親の val を override すると、コンパイルは成功するにも関わらず、実行時に ClassFormatError が出ます。
以下は現象を再現させるコード。

trait Base {
  val value: String = "base"
}
  
trait Child extends Base {
  override val value: String = "child"
}
  
object OverrideTraitSample {
  def main(args: Array[String]) {
    val target = new AnyRef with Child
    println(target.value)
  }
}

これをコンパイル&実行した結果は以下。


C:\development\workspaces\sandbox\scala-sandbox\src>scalac OverrideTraitSample.scala

C:\development\workspaces\sandbox\scala-sandbox\src>scala OverrideTraitSample
java.lang.ClassFormatError: Duplicate method name&signature in class file OverrideTraitSample$$anon$1
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:303)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
at OverrideTraitSample$.main(OverrideTraitSample.scala:11)
at OverrideTraitSample.main(OverrideTraitSample.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.ObjectRunner$$anonfun$run$1.apply(ObjectRunner.scala:75)
at scala.tools.nsc.ObjectRunner$.withContextClassLoader(ObjectRunner.scala:49)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:74)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:154)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

C:\development\workspaces\sandbox\scala-sandbox\src>

コンパイラのバグなのか何なのか・・・
ちなみに使用した scala のバージョンは 2.7.7 final です。

trait ではなく、無名クラスで override してみた場合、ClassFormatError は出ないですが、そもそも override 出来ていません :-P
無名クラスで override した例は以下。

// 〜trait Base は省略〜
object OverrideTraitSample {
  def main(args: Array[String]) {
    //val target = new AnyRef with Child
    val target = new Base { override val value = "anon" }
    println(target.value)
  }
}

コンパイル&実行結果は以下。


C:\development\workspaces\sandbox\scala-sandbox\src>scalac OverrideTraitSample.scala

C:\development\workspaces\sandbox\scala-sandbox\src>scala OverrideTraitSample
base

C:\development\workspaces\sandbox\scala-sandbox\src>

val を override 出来ていないため、"anon" ではなく、"base" が出力されている。
そもそも val は override できないのか・・・?

追記(2010/01/13)

ちょろっと仕様書の中をさがしてみましたが、trait の val は override 出来ないといった記述は発見できず。
ワークアラウンドですが、val ではなく def で定義しておけば期待どおりの結果になります。

trait Base {
  //val value: String = "base"
  def value: String = "base"
}
  
trait Child extends Base {
  //override val value: String = "child"
  override def value: String = "child"
}
  
object OverrideTraitSample {
  def main(args: Array[String]) {
    val target = new AnyRef with Child
    println(target.value)
  }
}


コンパイル&実行。


C:\development\workspaces\sandbox\scala-sandbox\src>scalac OverrideTraitSample.scala

C:\development\workspaces\sandbox\scala-sandbox\src>scala OverrideTraitSample
child

C:\development\workspaces\sandbox\scala-sandbox\src>


ちなみに Base と Child の両方を class にしても期待通り動きます。trait の場合だけ期待通りに動かないみたいですね。