在嵌套在对象中的trait中混合时的AbstractMethodError - 仅在编译和导入时

时间:2015-06-07 21:21:03

标签: scala inheritance traits

请考虑以下代码:

object Impls {
  trait ConcreteImpl {
    type Foo = Int
    def foo = 1
  }
}

trait Base {
  type Foo
  def foo: Foo
}

我对表达式感兴趣

(new Base with Impls.ConcreteImpl).foo

当我将上述代码粘贴到REPL中,或者在工作表中运行它,然后尝试表达式 - 没问题时,它会按预期打印res0: Int = 1

当我将代码放在一个文件中时,用scalac编译它,然后使用同一目录中REPL的已编译类文件,我得到相同的结果。

然而,当我使用编译的文件,然后从REPL说出来

import Impls._
(new Base with ConcreteImpl).foo

它抛出

java.lang.AbstractMethodError: $anon$1.foo()I

如果我将所有代码粘贴到REPL中,并使用导入变体,则会发生 not

这里发生了什么?这甚至是预期的行为吗?如果相关,我正在使用

Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_45)

1 个答案:

答案 0 :(得分:4)

这显然是一个错误。

如果你:

java.lang.AbstractMethodError: $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1.foo()I
  ... 33 elided

scala> :javap -p $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1
Compiled from "<console>"
public final class $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1 implements p.Base,p.Impls$ConcreteImpl {
  public java.lang.Object foo();
  public $line13.$read$$iw$$iw$$iw$$iw$$iw$$iw$$anon$1();
}

它没有结果类型为Int的

的foo

副手,我无法想象REPL的差异,但我们即将观看电影......不过你可以在Ammonite中尝试。

大多数此类错误是由于REPL是驻留编译器这一事实,但它对于如何影响现有类文件的编译并不明显。

编辑:

它首次使用完全限定名称,但在出现失败后,完全合格的失败了。

scala> (new p.Base with p.Impls.ConcreteImpl).foo // show
//works
res0: Int = 1

scala> import p._
import p._

scala> import Impls._
import Impls._

scala> (new Base with ConcreteImpl).foo // show
// fails
java.lang.AbstractMethodError: $anon$1.foo()I
  ... 33 elided

scala> (new p.Base with p.Impls.ConcreteImpl).foo // show
// also fails
java.lang.AbstractMethodError: $anon$1.foo()I
  ... 33 elided

这显然是常驻编译器错误。 (这里的类在包中。)

修改:实际上是SI-9689