2016-05-06 8 views
1

Scalaのコード:このスケーラコードを理解するには?

trait Action{ 
    def doAction 
} 

trait BeforeAfterOfAction extends Action{ 
    abstract override def doAction: Unit ={ 
     println("before") 
     super.doAction 
     println("after") 
    } 
} 

class Work extends Action{ 
    override def doAction = println("working....") 
} 
object Test{ 
    def main(args: Array[String]) { 
     val work = new Work with BeforeAfterOfAction 
     work.doAction 
    } 
} 

結果は次のとおりです。

before 
working.... 
after 

私はそれが唯一の "working...." を印刷しshoudと思いますが、なぜでしょうか?

プロセスの詳細を説明できますか?

+0

明示的に特性を混合すると、メソッドがオーバーライドされます。 –

+0

詳細を実行する順序を削除できますか? – Guo

+1

あなたの "スタック可能な"特性の '抽象'メソッドは実行可能な振る舞いを提供します - それはおそらくあなたが誤解していたビットです。 'abstract override def doAction'は' Work'のバージョンの前に実行されます。 Sudhirのリファレンスに加えて、Artimaのこの他のリソースも、ここで実装したパターンを説明するのに非常に良い仕事をしています - http://www.artima.com/scalazine/articles/stackable_trait_pattern.html – Nio

答えて

2

new Work with BeforeAfterOfActionと書くと、のスタック可能な動作の特性が使用されています。 Programming in Scalaからの抜粋:

形質は、クラスのメソッドを変更してみましょう、と彼らはあなたがお互いにそれらの変更をスタックすることを可能にする方法 で行います。

詳細はhereです。

EDIT

は、あなたが入力すると、さらにそれを説明するには:今

class MyWork extends Work with BeforeAfterOfAction 

:あなたが実際にクラス定義以下と等価であるミックスインを作成している

new Work with BeforeAfterOfAction 

MyWorkクラスの線形化は次のようになります。

doAction方法を持っていないよう
MyWork -> BeforeAfterOfAction -> Work -> Action -> AnyRef -> Any 

new MyWork()new Work with BeforeAfterOfActionと同等です)あなたがnew MyWork().doActionを呼び出すが、それは、BeforeAfterOfActionからdoAction起動します。

super.doActionBeforeAfterOfActiondoActionが出現すると興味深い部分が出ます。 superに遭遇すると、線形化の最初の右からdoActionが選択されます。この場合、doActionWorkです。したがって、次のような出力が表示されます。

thisリンクから線形化の詳細を読むことができます。 BAxのこのインスタンスは、特性(またはクラス)のミックスです

val x = new A with B with C 
x.meth() 

、およびC

1

は、次のことを考えてみましょう。方法meth()が呼び出されると、コンパイラは最初にCを調べ、そのメソッドが定義されているかどうかを確認します。見つからない場合はB、最後にAとなります。あなたの例では

val work = new Work with BeforeAfterOfAction 
work.doAction 

...方法 doActionはそれが実行されます一つだので、 BeforeAfterOfActionで発見されました。しかしその方法では super.doActionへの呼び出しです。 BeforeAfterOfActionのスーパークラスは何ですか?それは、その形質が混ざり合ったときにそれが前に来たものであった。

したがって、コンパイラはまずWorkを参照して、そこにdoActionメソッドが定義されているかどうかを確認します。それ以来、それは実行されるものです。

関連する問題