2016-04-29 10 views
0

Ich bin fest versucht Scala zu verstehen, erlaubt es nicht, die folgenden:Scala: val mit flüchtigen Typ überwiegendes def mit nichtflüchtigen Typ

trait WhatsWrong { 
    type Foo 

    trait HasFoo { 
    def foo: Foo 
    } 

    type Foo2 = Foo with HasFoo2 

    trait HasFoo2 extends HasFoo { 
    override val foo: Foo2 // <-- error here 
// override def foo: Foo2 // <-- this works though 
    } 
} 

Error: overriding method foo in trait HasFoo of type => WhatsWrong.this.Foo; value foo has a volatile type; cannot override a member with non-volatile type
override val foo: WhatsWrong.this.Foo2

Warum Foo2 einen flüchtigen Typ ist?

Antwort

1

Foo2 flüchtig nach http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#volatile-types: Der zweite Fall gilt: Foo2 = T1 with T2 mit T1 und T2 sind abstrakte beitrag einen abstrakten Typ Element.

Diese Fehlermeldung tritt immer auf, wenn Sie einen nichtflüchtigen Typ mit einem flüchtigen Typ überschreiben: Foo ist nicht flüchtig (weil keiner von 1.-3. Gilt). Also, um die Fehler zu machen weggehen, gibt es ein paar Möglichkeiten:

  • machen HasFoo.foo s Rückgabetyp volatil. Dies kann unter Verwendung von Foo with Foo anstelle von nur Foo (gemäß 3.6.1) erfolgen. Ich denke, abgesehen davon gibt es keinen Unterschied zwischen Foo with Foo und nur Foo. So ist der folgende Code kompiliert:

    trait WhatsWrong { 
        type Foo 
    
        trait HasFoo { 
        def foo: Foo with Foo 
        } 
    
        type Foo2 = Foo with HasFoo2 
    
        trait HasFoo2 extends HasFoo { 
        override val foo: Foo2 // <-- hey, now this works :) 
        // override def foo: Foo2 // <-- this works, too 
        } 
    } 
    
  • hm, ich dachte, dass es etwas möglich mit @uncheckedStable wäre (siehe http://www.scala-lang.org/files/archive/spec/2.11/11-annotations.html#scala-compiler-annotations), aber dies scheint nicht der Fall zu sein: mit Anmerkungen versehen, den flüchtigen Wert mit @annotations. unchecked.uncheckedStable scheint nicht zu helfen.

+0

Ich denke du hast einen Tippfehler: "Foo ~~ 2 ~~ ist nicht flüchtig (weil keiner von 1.-3. Gilt)". Sieht anders aus, danke! – eprst

+0

ja, du hast recht von grund, korrigiert –

1

Ich bin schon mal darauf gestoßen, es hängt mit der dynamischen Natur abstrakter (noch nicht definierter) Accessoren wie val und def zusammen. In diesem Fall benutze einfach def anstelle von val und es wird kompiliert.

trait HasFoo2 extends HasFoo { 
    override def foo: Foo2 // <-- error here 
    // override def foo: Foo2 // <-- this works though 
    } 
+0

ah Entschuldigung, ich habe nicht einmal gesehen, dass Sie bereits diese Lösung aufgeführt! – LaloInDublin