これらの恣意的な慣習は、他の慣習と同じくらい良いものですか?
いいえ、これらは任意ではありません。正しいMethod Resolution Order (MRO)を提供する唯一の方法であるため、線形化はこの方法で行われます。
クラスよりも特性が最初に調査され、その逆ではないのはなぜですか?
これは、特定のクラス定義にのみ当てはまります。つまり、それが拡張するトレイトは、それが拡張するクラスの前に来ます。これは、スーパークラス/特性が右から左に探索されるという事実から導き出されたものです。
特性が左から右ではなく、右から左にトラバースされるのはなぜですか?
これは非常に単純な動機付けの例です。
type MyType = T1 with T2
// Creating new instance using alias
new MyType with T3
// Creating new instance directly
new T1 with T2 with T3
上記の例の両方のインスタンスが同じ線形化を持つことが期待されます。型エイリアスを使用する場合、追加の特性を右側に「スタック」します。したがって、右側の特性が MRO で最も優先され、線形化で最初に来ることが期待されます。
トレイトとクラスの線形化を説明するために私が思いついた簡単な例を次に示します。
class Base { override def toString = "Base" }
trait A { abstract override def toString = "A " + super.toString }
trait B { abstract override def toString = "B " + super.toString }
trait C { abstract override def toString = "C " + super.toString }
trait D { abstract override def toString = "D " + super.toString }
trait E { abstract override def toString = "E " + super.toString }
trait F { abstract override def toString = "F " + super.toString }
class X extends Base with A with B { override def toString = "X " + super.toString }
class Y extends X with C with D { override def toString = "Y " + super.toString }
class Z extends Y with E with F { override def toString = "Z " + super.toString }
new Z
// res0: Z = Z F E Y D C X B A Base
toString
出力から、ここでの線形化が であることがわかりZ F E Y D C X B A Base
ます。これは、指定された階層で期待するものとまったく同じです。たとえば、 trait を mix-in するZ
extendsから、の動作は の前に来ると予想されますが、その mix-inとの後に来ると予想されます。Y
C
Y
C
Z
E
F
Programming in Scala, First Edition: Traits の第 12 章に関する簡単なリファレンスです。(これは最近変わっていないと思うので、初版はまだ正確なはずです。)