2017-10-05 14 views
1

次のコードでは、クラスBがA1を定義していても、特性CおよびDのメソッドA1が呼び出されるのはなぜですか?クラスにメソッドの実装があるときに特性のメソッドが呼び出される理由

scala> trait A { 
    | def A1 = A2 
    | def A2 //A2 is abstract and need implementation 
    | } 
defined trait A 

scala> class B extends A { 
    | def A2 = println("B") //implemented A2 in B 
    | } 
defined class B 

scala> val b1 = new B 
b1: B = [email protected] 

これは問題なく動作します。

scala> b1.A1 
B 

scala> b1.A2 
B 

現在、私は形質をミックスしています。 Cは、まだA2抽象

scala> trait C extends A { 
    | abstract override def A1 = {super.A1; C} 
    | def C = println("C") 
    | } 
defined trait C 

Dは、まだA2抽象強いテキスト私はBのA1は、BのA1は、唯一のBさんを呼び出すべきではありません呼び出すカム際にCとDが印刷されているのはなぜ

scala> trait D extends A { 
    | abstract override def A1 = {super.A1; D} 
    | def D = println("D") 
    | } 
defined trait D 

を持っていますA2はB?を印刷するために実装されていますか? D

b2: B with C with D = [email protected] 

scala> b2.A1 
B 
C 
D 

scala> b2.A2 
B 

scala> val b3 = new B with D with C 
b3: B with D with C = [email protected] 

scala> b3.A1 
B 
D 
C 
+0

達成したいことは何ですか?また、[trait linearizazion](https://stackoverflow.com/questions/34242536/linearization-order-in-scala)がScalaでどのように機能するかを見てください。例は完璧にうまく動作します。 –

+0

は、形質がどのように呼び出されるかを理解したい。私は今、ヒントを得ていると思う。 –

+0

'def'型のw/o型、' def'型の同じ名前(まだ型なし)、 'override' – cchantep

答えて

0

とCとの

スカーラ>ヴァルB2 =新しいB私は、私が使用していますが、積み重ね可能な形質のパターンと呼ばれるものとします。基本的には、new B with C with Dを使用してメソッドを呼び出すと、メソッドがDで定義されているかどうか、そして次にCとB(順序は右から左)が表示されます。コンパイラが実装を見るとき、それはそれを使用します。 superを使用すると、コンパイラは次の実装をクラスで使用できるように呼び出すか、左(再び右から左の順)の特性を呼び出します。

削除されたsuperが呼び出されます。 superとして

scala> trait D extends A { 
    | abstract override def A1 = { D} 
    | def D = println("D") 
    | } 
defined trait D 

scala> trait C extends A { 
    | abstract override def A1 = { C } 
    | def C = println("C") 
    | } 
defined trait C 

scala> val b3 = new B with D with C 
b3: B with D with C = [email protected] 

、除去コンパイラはA1に呼び出す見たとき、それはC最初(一番右の、順序は左から右である)、それはA1を見つけ、そのインプリメンテーションを使用して確認されます。 A1はスーパーを使用していないため、DまたはBA1が呼び出されていません。

scala> b3.A1 
C 

Dた場合は、右端のみDA1は、印刷後に追加super

scala> val b3 = new B with C with D 
b3: B with C with D = [email protected] 

scala> b3.A1 
D 

と呼ばれています。これにより、注文や印刷が変更されます。 superとして

scala> trait C extends A { 
    | abstract override def A1 = { C ; super.A1} 
    | def C = println("C") 
    | } 
defined trait C 

scala> val b3 = new B with C with D 
b3: B with C with D = [email protected] 

scala> b3.A1 
D 

と呼ばれ、DからA1を呼び出した後、コンパイラは、スーパークラス(左側の次の1)のA1を探し、左の方にいっています。

scala> val b3 = new B with D with C 
b3: B with D with C = [email protected] 

scala> b3.A1 
C 
D 

scala> 
0

なぜC及びDが、私はBのA1のみBを印刷するように実装されているBのA2を呼び出すべきではありませんBのA1を呼び出すCAMときに印刷されていますか?ないB#A2、ないA#A2が、this.A2

super.A1は、それが上と呼ばれるオブジェクトのA2を呼び出しA#A1を指します。

また、CDは、どのような方法でBに関連していないので、彼らはどのような場合にB#A1を呼び出すことができませんでした:あなたはclass C/D extends Bを意味するのですか?

関連する問題