2016-07-29 44 views
3

Ich entdeckte, dass die Verwendung abstrakter Typen die Fähigkeit des Scala-Compilers beeinträchtigt, Überschreibungen zu erkennen, und scheinbar korrekten Code als fehlerhaft interpretiert.Warum schlägt die abstrakte Überschreibung fehl

trait I { 
    type T 
    def doThings(t : T) : Unit 
} 
type IT[X] = I { type T = X} 

trait A extends I { 
    override type T = AnyRef 
    def doThings(t : T) : Unit = println("A") 
} 

trait Z[X] extends I { this : IT[X] => 
    abstract override def doThings(t : T) : Unit = { 
    println("Z") 
    super.doThings(t) 
    } 
} 

object Use { 
    val az = new A with Z[AnyRef] {} 
} 

Der scala Compiler Brände solche Fehler:

OverloadAbstract.scala:44: error: object creation impossible, since method doThings in trait Z of type (t: this.T)Unit is marked `abstract' and `override', but no concrete implementation could be found in a base class 
    val az = new A with Z[AnyRef] {} 

Was ist der richtige Weg, um solche Beziehungen zwischen Zug zum Ausdruck bringen Mischen und Umsetzung?


Für den Vergleich funktioniert dieser Code in Ordnung:

trait I { 
    def doThings() : Unit 
} 

class A extends I { 
    def doThings() : Unit = println("A") 
} 

trait Z extends I { 
    abstract override def doThings() : Unit = { 
    println("Z") 
    super.doThings() 
    } 
} 

object Use { 
    val az = new A with Z {} 
} 

Die eigentliche Anwendungsfall ist eine Weiterleitung für die akka.event.EventBus zu implementieren:

object PartialEventBus { 
    type ApplyEvent[E] = EventBus { type Event = E } 
} 

trait ForwardEventBus[E] extends EventBus { this : PartialEventBus.ApplyEvent[E] => 
    def relay : PartialEventBus.ApplyEvent[E] 

    abstract override def publish(event : Event) : Unit = { 
    relay.publish(event) 
    super.publish(event) 
    } 
} 

Typ Parametrisierung für die ForwardEventBus wird benötigt, damit der Compiler objektweit übereinstimmt this.Event Typ mit externen relay.Event Typ. Der Compiler würde ohne einen solchen Hinweis aufgrund von scalas pfadabhängigen Typeneinschränkungen scheitern.

+1

Es verliert 'T', da self-type' self: A => 'funktioniert. Vielleicht kann jemand sagen warum. Es ist schwierig, Grenzen für Mitglieder des abstrakten Typs zu bekommen, die mit Selbsttypen arbeiten, aber ich sehe den Grund hier nicht ohne weiteres. –

Antwort

0

Vielleicht bin ich verwirrt, sollte nicht die Frage sein "Warum funktioniert abstrakte Override?" Abschnitt 5.2.4 der Spezifikation deckt abstract override ab und besagt: "Der Überschreibungsmodifikator hat eine zusätzliche Bedeutung, wenn er mit dem abstrakten Modifikator kombiniert wird. Diese Modifikatorkombination ist nur für Wertelemente von Merkmalen zulässig."

Ich hoffe ein Sprachanwalt kann wiegen, aber es sieht so aus, als ob dies nicht legal sein sollte.

+0

sehr seltsam, abstrakte Override-Methoden sind weit verbreitet: http://www.artima.com/scalazine/articles/stackable_trait_pattern.html – ayvango