web-dev-qa-db-ja.com

Scalaで複数の特性を混合する

クイックノート:チュートリアルの例 Scala for Java Refugees Part 5:Traits and Types)。

私には、Student、Worker、Underpaid、Youngという特性があるとします。

クラス(ではなくインスタンス)、CollegeStudentをこれらすべての特性で宣言するにはどうすればよいですか?

注:1つまたは2つの特性を持つCollegeStudentなど、最も単純なケースを認識しています。

class CollegeStudent extends Student with Worker
50
Daniel Ribeiro

クラスを宣言するときは、「with」キーワードを必要なだけ使用するだけです。

class CollegeStudent extends Student with Worker with Underpaid with Young

特性がクラスの動作を変更している場合、特性の順序は重要になる可能性があります。すべては使用している特性に依存します。

また、常に同じ特性を使用するクラスが必要ない場合は、後で使用できます。

class CollegeStudent extends Student
new CollegeStudent with Worker with Underpaid with NotSoYoungAnymore
98
Alexander Stolz

構文だけでなく、を説明することも非常に重要だと思います。(== --- ==)また、どの役割が特性の順序を果たしますか。 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
_

これは、線形化された継承グラフの構造を完全に反映しています。

10
fr_andres