请考虑以下代码:
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)
答案 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。