2014-05-14 7 views
22

Ich lese die section von Programmierung in Scala, wo abstract override eingeführt wird, aber ich bin immer noch verwirrt, was genau durch die Verbindung dieser Modifikatoren bezeichnet wird. Der Code-Snippet, in denen diese Modifikatoren verwendeten unten eingefügt werden:Warum ist "abstrakte Überschreibung" erforderlich, nicht "überschreiben" allein in subtrahieren?

trait Doubling extends IntQueue { 
    abstract override def put(x: Int) { super.put(2 * x) } 
} 

Insbesondere ist ich von dem Zweck der abstract in diesem Fall verwirrte, und warum können wir die erwarteten Ergebnisse einfach mit dem override Schlüsselwort nicht erreichen. Wenn wir keinen Anruf zu super einschließen würden, würden wir das Schlüsselwort abstract benötigen? Warum oder warum nicht? Ich bin auf der Suche nach einer detaillierten Erklärung dieser Keyword-Combo, da es sich um stapelbare Eigenschaften handelt.

Antwort

18

Der Grund dafür ist, dass die Basisklassenmethode ist abstrakt

abstract class IntQueue { 
    def get(): Int 
    def put(x: Int) 
} 

Wenn Sie nicht auf die Sie mit der Erklärung bis setzen abstract Zug am Ende waren Sie suchten:

trait Doubling extends IntQueue { 
    override def put(x: Int) { super.put(2 * x) } 
} 
<console>:9: error: method put in class IntQueue is accessed from 
super. It may not be abstract unless it is overridden by a member 
declared `abstract' and `override' 
      override def put(x: Int) { super.put(2 * x) } 

Also - Sie müssten die Methode als abstract markieren. Hier

ist die „andere Seite“ der Gleichung: Wenn die Methoden Implementierungen haben, dann ist es nicht notwendig die trait ‚s Methode als abstract zu markieren:

abstract class IntQueue { 
    import collection.mutable._ 
     val q = Queue[Int]() 
     def get(): Int = { q.dequeue() } 
     def put(x: Int) = { q.enqueue(x) } 
    } 

Es ist nun nicht notwendig ist abstract enthalten

trait Doubling extends IntQueue { 
     /* Look Ma! no abstract here ! */ override def put(x: Int) { super.put(2 * x) } 
     } 
defined trait Doubling 
+1

_Thank you_. Aus irgendeinem Grund sehe ich weiterhin stapelbare Merkmalsbeispiele mit 'abstrakte Überschreibung', aber es scheint mir, dass die beiden Konzepte tatsächlich getrennt sind (obwohl beide auf dynamisch gebundene 'Super' angewiesen sind). – Max

5

die Idee ist, dass es eine unvollständige Überschreibung ist - Sie noch die schließlich konkrete Umsetzung des Merkmals erforderlich sein soll, dass die Verfahren zur Verfügung zu stellen, auch wenn Sie diese hypotheti sind modifizierende das Verhalten der cal-Methode. Mit anderen Worten, die Methode, die Sie überschreiben, ist keine vollständige Standalone-Implementierung. Es gibt einen ähnlichen Effekt wie eine method decorator könnte in Python.

Soweit ich folgern kann, ist eine Methode auf einem Merkmal abstract override, wenn und nur wenn es nennt super, aber es bricht Verkapselung den Client des Codes zu erwarten, dass die Durchführung des Verfahrens zu untersuchen, um zu wissen, dass es einen konkreten Bedürfnisse Implementierung. Daher müssen Sie es abstract override markieren, um die Schnittstelle vollständig zu definieren.

2

Ein Teil von late binding in scala traits Pfosten; liefert eine sehr klare Erklärung; (siehe die full post für weitere Informationen):

Die abstrakte Basisklasse zur Verfügung gestellt eine Implementierung der requestApproval Methode. Dies ist gut, da das Merkmal ganz links diese Methode aufruft. Was passiert, wenn die Methode der Basisklasse abstrakt ist?

abstract class ApprovalRequest { 
    def requestApproval() 
} 

Wenn wir dies zu ändern, bekommen wir eine ziemlich seltsam Nachricht vom Compiler: Fehler: Methode requestApproval in Klasse ApprovalRequest von Super zugegriffen werden.Es kann nicht abstrakt sein, wenn sie von einem Mitglied außer Kraft gesetzt wird erklärt abstract und override Die Kombination aus abstract und override teilt den Compiler mit, dass die endgültige Implementierung des Verfahrens wird durch die Klasse Misch im Zuge zur Verfügung gestellt werden. Wenn wir den Methoden das Schlüsselwort abstract hinzufügen, können wir unsere anonyme Implementierung von ApprovalRequest nicht mehr verwenden. Dieses Objekt kann nicht erstellt werden, da die abstrakten Override-Methoden nach einer Implementierung von requestApproval suchen und es keine gibt. Stattdessen müssen wir eine neue Klasse erstellen, die ApprovalRequest erweitert und requestApproval implementiert. Wir mischen dann die Eigenschaften in eine Instanz dieser Klasse.

class ApprovalDelegate extends ApprovalRequest { 
    override def requestApproval() { 
    println("and now we play the waiting game") 
    } 
} 

val adCampaign = new ApprovalDelegate with MarketingApprovalRequest 
    with FinanceApprovalRequest with ExecutiveApprovalRequest 

die nun den Ausgang geben:

requesting approaval from executives 
requesting approval from Finance 
requesting approval from Marketing 
and now we play the waiting game 
Verwandte Themen