2012-08-08 11 views
8

Voglio creare una classe covariante che è mutabile, quindi ho bisogno di aggiungere un tipo più basso legato al metodo setter. Ma voglio anche che il metodo setter per impostare un campo, quindi immagino che il campo debba avere lo stesso tipo associato?Tipo inferiore associato al campo Scala nella classe mutevole, covariante?

class Thing[+F](initialValue: F) { 

    private[this] var secondValue: Option[G >: F] = None 

    def setSecondValue[G >: F](v: G) = { 
     this.secondValue = Some(v) 
    } 
} 

Il metodo si compila bene. Ma il campo chiamato secondValue non viene compilato affatto, con il messaggio di errore:

Multiple markers at this line 
     - ']' expected but '>:' found. 
     - not found: type G 

Cosa devo fare?

risposta

8

è necessario il forSome costrutto, che introduce G come tipo esistenziale:

class Thing[+F](initialValue: F) { 
    private[this] var secondValue: Option[G] forSome { type G >: F} = None 

    def setSecondValue[G >: F](v: G) = { 
    this.secondValue = Some(v) 
    } 
} 

Nel codice originale per secondValue, G è stato tirato fuori dal nulla, cioè, non è stato introdotto correttamente. In caso di setSecondValue l'utente (o il compilatore) associa G al sito di chiamata, ma per un campo che non è un'opzione (soprattutto, poiché il tuo è privato). Ulteriori informazioni su forSome e tipi esistenziali in Scala here, here o here.

+0

Perfetto - fa quello che voglio. Ho provato a usare forSome sul metodo e funziona anche: def setSecondAroma (secondAroma: G forSome {tipo G>: F}) = ... –

+0

@JohnSmith Non so se l'uso di forSome G in setSecondValue ha qualche (dis) vantaggi rispetto ad avere un argomento di tipo regolare G. Se lo sapessi/lo scoprirai, per favore postalo qui. –

+2

Nota che il tipo 'G' nel campo non ha nulla a che fare con il tipo' G' nel metodo qui. –

11

@mhs risposta è giusta.

È possibile anche utilizzare la sintassi jolly (come in Java), che ha esattamente lo stesso significato:

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

class Thing[+F](initialValue: F) { 
    private[this] var secondValue: Option[_ >: F] = None 

    def setSecondValue[G >: F](v: G) = { 
    this.secondValue = Some(v) 
    } 

    def printSecondValue() = println(secondValue) 
} 

// Exiting paste mode, now interpreting. 

defined class Thing 

scala> val t = new Thing(Vector("first")) 
t: Thing[scala.collection.immutable.Vector[java.lang.String]] = [email protected] 

scala> t.printSecondValue() 
None 

scala> t.setSecondValue(Seq("second")) 

scala> t.printSecondValue() 
Some(List(second)) 
+0

hmm, penso di aver accettato troppo in fretta. questa sembra una soluzione più elegante. –

Problemi correlati