2016-07-07 13 views
11

Ich versuche, Fallobjekte Typen als abstrakte Typen zu verwenden. Ich war überrascht zu sehen (ähnlich) folgender Code kompiliert:Wie man abstrakten Typ mit gebundenem Typ konkret festlegt?

sealed abstract class Bar 

case object BarOne extends Bar 

case object BarTwo extends Bar 

sealed abstract class Foo { 
    type A <: Bar 

    def f: A 
} 

object Foo { 
    object FooOne extends Foo { 
    type A = BarOne.type 
    val f = BarTwo 
    } 

    object FooTwo extends Foo { 
    type A = BarTwo.type 
    val f = BarOne 
    } 
} 

In meinem realen Beispiel Foo parametrisiert und als Fall-Klasse verwendet. Also kann ich nicht einfach einen Typparameter A machen. Wie wird f = BarTwo kompiliert, wenn A auf BarOne.type eingestellt ist? Wenn die Af: A als A <: Bar interpretiert wird, warum ist das so?

Gibt es eine Möglichkeit, A für jede Objektinstanz von Foo konkret festzulegen?


Ich benutze Scala 2.11.8.


Update: wenn ich val attributeType = ... mit def attributeType = ... in FooOne & FooTwo Zusammenstellung ersetzen nicht (wie erwartet).

+1

Ist das fehlende 'erstreckt Foo' auf' FooOne' und 'FooTwo' einen Tippfehler? Weil es nicht kompiliert, wenn Sie das hinzufügen. –

+0

@ EndeNeu Es war ein Versehen. Und du hast Recht, es kompiliert nicht (wie erwartet). Ich habe die Frage aktualisiert, damit sie so nah wie möglich am echten Code aussieht. Natürlich ist es nutzlos, da der obige Code nicht kompiliert und mein Code kompiliert wird. – muhuk

+1

@muhuk Wenn der obige Code nicht kompiliert, dann stellt es nicht Ihren kompilierenden Code dar. Diese Frage ist nicht zu beantworten, es sei denn, Sie erhalten ein korrektes minimales Beispiel. – Daenyth

Antwort

1

Hat Ihnen jemand vorgeschlagen, auf eine moderne Version von Scala zu aktualisieren? (Witz.)

Der Fehler über die Überschreibung gibt einen schönen Pfad für den Typ.

$ scala 
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92). 
Type in expressions for evaluation. Or try :help. 

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

sealed abstract class Bar 

case object BarOne extends Bar 

case object BarTwo extends Bar 

sealed abstract class Foo { 
    type A <: Bar 

    def f: A 
} 

object Foo { 
    object FooOne extends Foo { 
    type A = BarOne.type 
    val f = BarTwo 
    } 

    object FooTwo extends Foo { 
    type A = BarTwo.type 
    val f = BarOne 
    } 
} 

// Exiting paste mode, now interpreting. 

<console>:26: error: overriding method f in class Foo of type => Foo.FooOne.A; 
value f has incompatible type 
      val f = BarTwo 
      ^
<console>:31: error: overriding method f in class Foo of type => Foo.FooTwo.A; 
value f has incompatible type 
      val f = BarOne 
      ^

Der Fehler war this one und die doppelte Frage ist from last November.

Die Art des Fehlers war auch clever: Es wurde von -Yoverride-objects eingeführt, die keine sehr nützliche Option ist, aber Zahlen in ein paar meiner S.O. Antworten und jetzt in einer Frage.

Edit:

$ scala 
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92). 
Type in expressions for evaluation. Or try :help. 

scala> object X ; object Y 
defined object X 
defined object Y 

scala> class C { def f: X.type = X } 
defined class C 

scala> class D extends C { override def f: Y.type = Y } 
defined class D 

scala> :quit 
$ scalam 
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92). 
Type in expressions for evaluation. Or try :help. 

scala> scala> object X ; object Y 

// Detected repl transcript. Paste more, or ctrl-D to finish. 

defined object X 
defined object Y 

scala> class C { def f: X.type = X } 
defined class C 

scala> class D extends C { override def f: Y.type = Y } 
defined class D 
// Replaying 3 commands from transcript. 

scala> object X ; object Y 
defined object X 
defined object Y 

scala> class C { def f: X.type = X } 
defined class C 

scala> class D extends C { override def f: Y.type = Y } 
<console>:13: error: overriding method f in class C of type => X.type; 
method f has incompatible type 
     class D extends C { override def f: Y.type = Y } 
             ^
1

Ich weiß nicht, was hier vor sich geht, aber ich habe das Problem etwas isolierter bekommen. Außerdem funktioniert es sowohl mit Foo-Unterklassen als auch mit Objekten.

object BarOne 
object BarTwo 

abstract class Foo[A] { 
    def attributeType: A 
} 

object FooContainer { 
    class FooOne extends Foo[BarOne.type] { 
    val attributeType = BarTwo 
    } 

    object FooTwo extends Foo[BarOne.type] { 
    val attributeType = BarOne 
    } 
} 
+0

Danke. Aber das ist keine Antwort. – muhuk

+0

Ja, ich wusste nicht, wie man sonst auf Stack Overflow ein großes Codefragment bekommt. – robot1208

0
  1. A in f:: Ich habe diese 2.11.8 kompiliert auf scalac bestätigt A als A interpretiert <: Bar
  2. Denn das ist es, was A darstellt, wenn F in der abstrakten Klasse definiert ist
  3. Wie wäre es die abstrakte Definition überschrieben (die unten kompilieren nicht):

    object Foo { 
    
        object FooOne extends Foo { 
        type A = BarOne.type 
        override val f: A = BarTwo 
        } 
    
        object FooTwo extends Foo { 
        type A = BarTwo.type 
        override val f: A = BarOne 
        } 
    
    }