構文だけでなく、トレイトの順序付けがどのような役割を果たしているのかを説明することは非常に重要だと思います。Jason Swartz のLearning Scala (page 177) の説明は非常に啓発的でした。
Scala クラスは一度に複数のトレイトを拡張できますが、JVM クラスは 1 つの親クラスしか拡張できません。Scala コンパイラーは、「各特性のコピーを作成して、クラスと特性の背の高い単一列の階層を形成する」ことでこれを解決します。これは線形化と呼ばれるプロセスです。
このコンテキストでは、同一のフィールド名を持つ複数のトレイトを拡張するとコンパイルに失敗し、「クラスを拡張して独自のバージョンのメソッドを提供するがオーバーライド キーワードの追加に失敗した場合とまったく同じ」です。
また、継承ツリーの形状が決定されるため、線形化の順序は非常に重要な問題の 1 つです。例として、class D extends A with B with C
(A はクラス、B と C はトレイト) は になりclass D extends C extends B extends A
ます。同じく本からの次の数行は、それを完全に示しています。
trait Base { override def toString = "Base" }
class A extends Base { override def toString = "A->" + super.toString }
trait B extends Base { override def toString = "B->" + super.toString }
trait C extends Base { override def toString = "C->" + super.toString }
class D extends A with B with C { override def toString = "D->" + super.toString }
を呼び出すとnew D()
、REPL は次のように出力します。
D->C->B->A->Base
これは、線形化された継承グラフの構造を完全に反映しています。