Scalaではclassの定義時にtraitをmix-inできる。
scala> trait A // defined trait A scala> class B extends A // defined class B scala> val o1 = new B val o1: B = B@36b53f08
この時、変数の型はBと推論されている。
また、オブジェクトの生成時にもmix-inできる。この時の型は先ほどと異なる結果となる。
scala> class C // defined class C scala> val o2 = new C with A val o2: C & A = anon$1@5486ee92
この時の型はScala3から導入されたIntersection型により、変数はCとAを同時に持つ型として推論されている。
変数定義だけでなく、当然引数の型の宣言でも使える。
scala> def method(obj: A & C) = println(obj.toString) def method(obj: A & C): Unit scala> method(o2) repl$.rs$line$6$$anon$1@5486ee92
Intersectionには型の継承関係が整理されているので、詳しくは公式ドキュメントを見ると良い。
Scala2の時は、Compound Typeという型で推論されていた。
scala> trait A defined trait A scala> class C defined class C scala> val o = new C with A o: C with A = $anon$1@ecd379a
もちろん明示的に指定できる。
scala> val o2: C with A = new C with A o2: C with A = $anon$1@22c7ef94
この変数の型におけるwithを使ったCompound Typeの記法は将来は廃止される予定であるとされている。
Scala3で明示的に指定してもIntersectionで置き換えられている。
scala> val o4: A with C = new C with A val o4: A & C = anon$1@799971ac