2016-05-26 20 views
0

Ich habe eine Scala Compiler Fehler Puzzle, dass ich nicht herausfinden kann. Aus Gründen, die hier nicht angegeben sind, muss ich meine Klassen mit der curiously recurring template pattern deklarieren. Einige meiner Klassen müssen andere als Parameter enthalten. Zum Beispiel sieht eine abgespeckte Version von meinem Code wie folgt aus:Seltsam wiederkehrende Vorlage Muster Einschränkungen mit Scala abstrakten Typen

trait Container[C <: Container[C]] { 
    def stuff: C 
} 

trait Aggregation { 
    def fill(x: Double): Unit 
} 

class Counted extends Container[Counted] { 
    def stuff = this 
} 

class Counting extends Container[Counting] with Aggregation { 
    def stuff = this 
    def fill(x: Double) { } 
} 

class Binned[V <: Container[V]](v: V) extends Container[Binned[V]] { 
    def stuff = this 
    def substuff = v 
} 

class Binning[V <: Container[V] with Aggregation](v: V) extends Container[Binning[V]] with Aggregation { 
    def stuff = this 
    def substuff = v 
    def fill(x: Double) { } 
} 

Die oben genannten Arbeiten in Ordnung. Nun möchte ich auf jeden -ed eine abstrakte Art von jedem -ing hinzuzufügen:

trait Container[C <: Container[C]] { 
    type Ed <: Container[Ed] 
    def stuff: C 
} 

trait Aggregation { 
    def fill(x: Double): Unit 
} 

class Counted extends Container[Counted] { 
    type Ed = Counted 
    def stuff = this 
} 

class Counting extends Container[Counting] with Aggregation { 
    type Ed = Counted 
    def stuff = this 
    def fill(x: Double) { } 
} 

class Binned[V <: Container[V]](v: V) extends Container[Binned[V]] { 
    type Ed = Binned[V] 
    def stuff = this 
    def substuff = v 
} 

class Binning[V <: Container[V] with Aggregation](v: V) extends Container[Binning[V]] with Aggregation { 
    type Ed = Binned[V#Ed] 
    def stuff = this 
    def substuff = v 
    def fill(x: Double) { } 
} 

und der Compiler hat die Nerven, mir zu sagen

<console>:34: error: type arguments [V#Ed] do not conform to class Binned's type parameter bounds [V <: Container[V]] 
      type Ed = Binned[V#Ed] 

wenn Ed deutlich <: Container[Ed] für alle Containers ist.

Genau genommen, Typ Ed wird nur auf Containers with Aggregation benötigt, und wenn ich es dorthin verschiebe, bekomme ich den gleichen Fehler.

Weiß jemand, wie ich dem Compiler meine Absicht mitteilen kann?

Antwort

1
class Binning[V <: Container[V] with Aggregation](val v: V) extends Container[Binning[V]] with Aggregation { 
    type Ed = Binned[v.Ed] 
    def stuff = this 
    def substuff = v 
    def fill(x: Double) { } 
} 

funktioniert. Aber es scheint mir, als ob deine Version auch kompilieren sollte.

+0

Danke, fantastisch, fantastisch! Ich schmettere mich auf die Stirn für solch eine offensichtliche Lösung, obwohl ich zustimme, dass es scheint, als ob beide funktionieren sollten. –

+0

Es ist erwähnenswert, dass das "val" in der Argumentliste notwendig wird, da wir nicht auf "v.Ed" verweisen können, wenn "v" privat ist. In meinem Anwendungsfall möchte ich, dass "v" öffentlich ist, also ist alles in Ordnung. –

+0

Ich schlage vor zu fragen, warum 'V # Ed' nicht in der Mailingliste scala-user kompiliert wird, wenn Sie keine Antwort darauf erhalten. –