2016-07-07 17 views
11

Sto tentando di utilizzare i tipi di oggetti caso come tipi astratti. Sono rimasto sorpreso di vedere (simile) codice qui sotto compila:Come impostare concretamente il tipo astratto con il tipo bound?

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 
    } 
} 

Nel mio esempio reale Foo viene parametrizzata e usato come una classe case. Quindi non posso semplicemente creare un parametro di tipo A.

Come viene compilato f = BarTwo, quando A è impostato su BarOne.type?

Se A in f: A viene interpretato come A <: Bar, perché è così?

C'è un modo per impostare in modo concreto A per ciascuna istanza di oggetto di ?


Sto utilizzando Scala 2.11.8.


Aggiornamento: quando sostituisco val attributeType = ... con def attributeType = ... in FooOne & FooTwo compilazione fallisce (come previsto).

+1

è mancante 'estende foo' su' 'FooOne' e FooTwo' un errore di battitura? Perché non si compila se lo aggiungi. –

+0

@EndeNeu Era una svista. E hai ragione, non si compila (come previsto). Ho aggiornato la domanda per renderla il più simile possibile al codice reale. Ovviamente è inutile poiché il codice sopra non viene compilato e il mio codice viene compilato. – muhuk

+1

@muhuk se il codice sopra non viene compilato, non rappresenta il codice di compilazione. Questa domanda non risponde se non si ottiene un esempio minimo corretto. – Daenyth

risposta

1

Qualcuno ha suggerito di eseguire l'aggiornamento a una versione moderna di Scala? (Joke.)

L'errore sull'override fornisce un percorso piacevole per il tipo.

$ 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 
      ^

il bug è stato this one, e la questione è duplicato from last November.

La natura del bug era anche intelligente: è stata introdotta da -Yoverride-objects, che non è un'opzione molto utile, ma figura in un paio di miei S.O. risposte, e ora in una domanda.

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

Non so cosa sta succedendo qui, ma ho risolto il problema un po 'di più. Inoltre, funziona con sottoclassi Foo e oggetti. Ho confermato questo compila lo scalac 2.11.8:

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

Grazie. Ma questa non è una risposta. – muhuk

+0

Sì, non sapevo come ottenere un grande frammento di codice su Stack Overflow altrimenti. – robot1208

0
  1. A a F: A viene interpretato come una <: Bar
  2. Perché questo è ciò che A rappresenta quando F è definito nella classe astratta
  3. Come circa sovrascrivendo la definizione astratta (il seguito sarà non compilare):

    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 
        } 
    
    } 
    
Problemi correlati