2016-05-06 8 views
1

der scala Code:Wie versteht man diesen Scala-Code?

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 
    } 
} 

das Ergebnis:

before 
working.... 
after 

ich denke, es shoud nur "working...." drucken, aber warum nicht?

Können Sie Prozessdetails erklären?

+0

Sie haben das Merkmal explizit gemischt, deshalb wird Ihre Methode überschrieben. –

+0

Können Sie die Reihenfolge der Ausführung des Details erweitern? – Guo

+1

Die 'abstract' Methode in Ihrem" stackable "Merkmal bietet ausführbares Verhalten - das ist wahrscheinlich das Bit, das Sie falsch verstanden haben, dh. 'abstract override def doAction' wird vor' Work's Version ausgeführt. Zusätzlich zu Sudhirs Referenz macht diese andere Ressource von Artima auch eine ziemlich gute Arbeit, um das Muster zu erklären, das Sie hier implementiert haben - http://www.artima.com/scalazine/articles/stackable_trait_pattern.html – Nio

Antwort

2

Wenn Sie new Work with BeforeAfterOfAction schreiben, verwenden Sie Stack-fähiges Verhalten von Merkmalen. Auszug aus Programming in Scala:

Traits können Sie die Methoden einer Klasse ändern, und sie tun dies in einer Weise , dass Sie diese Änderungen miteinander stapeln kann.

Sie können es here im Detail lesen.

EDIT

es weiter zu erklären, wenn Sie Folgendes eingeben:

new Work with BeforeAfterOfAction 

Sie tatsächlich eine mixin zu schaffen, die auf unter Klassendefinition entspricht:

class MyWork extends Work with BeforeAfterOfAction 

Nun ist die Linearisierung für MyWork Klasse wird wie folgt sein:

MyWork -> BeforeAfterOfAction -> Work -> Action -> AnyRef -> Any 

Wenn Sie rufen new MyWork().doAction (wo new MyWork() entspricht new Work with BeforeAfterOfAction ist), ruft sie doAction von BeforeAfterOfAction, als MyWork nicht doAction Methode hat.

Interessante Teil kommt, wenn super.doAction in BeforeAfterOfActiondoAction angetroffen wird. Wenn super angetroffen wird, wird doAction von der ersten rechts in der Linearisierung ausgewählt. Was in diesem Fall ist doAction von Work. Daher sehen Sie eine Ausgabe wie:

before 
working.... 
after 

Sie mehr über Linearisierung von this Link zu lesen.

1

Beachten Sie Folgendes:

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

Diese Instanz von x ist eine Mischung von Eigenschaften (oder Klassen) A, B und C. Wenn die Methode meth() aufgerufen wird, sucht der Compiler zuerst in C, um zu sehen, ob es diese Methode definiert. Wenn es nicht gefunden wird, wird es in B und schließlich in A aussehen.

In Ihrem Beispiel:

val work = new Work with BeforeAfterOfAction 
work.doAction 

... die Methode doAction in BeforeAfterOfAction gefunden, das ist also derjenige, der ausgeführt wird. Aber in diesem Verfahren ist der Anruf zu super.doAction. Was ist die Super-Klasse von BeforeAfterOfAction? Es ist alles, was vorher kam, als die Eigenschaften gemischt waren.

Daher sieht der Compiler zuerst Work, um zu sehen, ob dort eine doAction Methode definiert ist. Da es ist, wird das ausgeführt.

Verwandte Themen