これは、Scala のすべての交差タイプが JVM バイトコードにコンパイルされる方法です。JVM には のようなものを表す方法がないInt with Foo
ため、コンパイラは型を最初の「単純な」型に消去しInt
ます。この場合。a
これは、値を a のように使用する場合Foo
、コンパイラはキャストをバイトコードに挿入する必要があることを意味します。
次の REPL セッションを見てください。
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.
scala> trait Foo { def foo = "foo" }
defined trait Foo
scala> trait Bar { def bar = "bar" }
defined trait Bar
scala> class FooBar extends Foo with Bar
defined class FooBar
scala> class Test { val foobar: Foo with Bar = new FooBar }
defined class Test
scala> object Main {
| def main(): Unit = {
| val test = new Test().foobar
| println(test.foo)
| println(test.bar)
| }
| }
defined object Main
scala> :javap -p -filter Test
Compiled from "<console>"
public class Test {
private final Foo foobar;
public Foo foobar();
public Test();
}
scala> :javap -c -p -filter Main
Compiled from "<console>"
...
public void main();
Code:
...
15: invokeinterface #62, 1 // InterfaceMethod Foo.foo:()Ljava/lang/String;
...
27: checkcast #23 // class Bar
30: invokeinterface #69, 1 // InterfaceMethod Bar.bar:()Ljava/lang/String;
...
Int with Foo
実際には特殊なケースです。Int
は最終型でFoo
あり、特性です。どうやらコンパイラは、特性よりも最終的な型とクラスを好むようです。そのため、Foo with Bar
whereFoo
は trait であり、Bar
is はクラスであっても、型は のBar
代わりに消去されFoo
ます。