クイックノート:チュートリアルの例 Scala for Java Refugees Part 5:Traits and Types)。
私には、Student、Worker、Underpaid、Youngという特性があるとします。
クラス(ではなくインスタンス)、CollegeStudentをこれらすべての特性で宣言するにはどうすればよいですか?
注:1つまたは2つの特性を持つCollegeStudentなど、最も単純なケースを認識しています。
class CollegeStudent extends Student with Worker
クラスを宣言するときは、「with」キーワードを必要なだけ使用するだけです。
class CollegeStudent extends Student with Worker with Underpaid with Young
特性がクラスの動作を変更している場合、特性の順序は重要になる可能性があります。すべては使用している特性に依存します。
また、常に同じ特性を使用するクラスが必要ない場合は、後で使用できます。
class CollegeStudent extends Student
new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore
構文だけでなく、を説明することも非常に重要だと思います。(== --- ==)また、どの役割が特性の順序を果たしますか。 Jason Swartzの Learning Scala (177ページ)の説明は非常に啓発的でした。
Scalaクラスは複数の特性を一度に拡張できますが、JVMクラスは1つの親クラスのみを拡張できます。Scalaコンパイラは、 "クラスとトレイトの高い単一列階層を形成する各トレイトのコピー"、linearization。
このコンテキストでは、同じフィールド名で複数の特性を拡張するとコンパイルに失敗します。クラスを拡張して独自のバージョンのメソッドを提供し、オーバーライドの追加に失敗した場合とまったく同じ「キーワード"。
そして、それが継承ツリーの形状を決定するため、線形化の順序は実際に考慮すべき非常に重要な質問の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
_
これは、線形化された継承グラフの構造を完全に反映しています。