Data una definizione di classe con il parametro tipo associato Animal[A <: String]
, sembra che il compilatore Scala non deduca B <: String
da Animal[B]
. L'inferenza è permessa? Come aiutare il compilatore a fare l'inferenza?Come definire le classi dei casi con membri con parametri di tipo non associato?
Di seguito è riportato un esempio concreto con classi di casi in cui la mancanza di questa inferenza è un problema.
Si consideri il seguente gerarchia di classe caso:
sealed trait Person[+T <: Person[T]]
case class Student() extends Person[Student]
case class Professor() extends Person[Professor]
Ho bisogno di definire una classe case University
cui posso istanziare con una variabile di tipo Person[_]
, per esempio val p: Person[_] = Student()
. Ho pensato che questo avrebbe funzionato con la seguente definizione:
case class University(p: Person[_])
Ma questo viene a mancare la compilazione con l'errore:
type arguments [Any] do not conform to trait Person's type parameter bounds [+T <: Person[T]]
Se mi legano il parametro type della classe caso University
compila (compila anche con parametri non limitati se lascio cadere la parola case
, ma questo non è un'opzione nel mio caso):
case class BoundUniversity[P <: Person[P]](p: Person[P])
ma questa versione parametrizzata non può essere istanziata con una variabile illimitata di tipo Person[_]
:
val p: Person[_] = Student()
BoundUniversity(p)
fallisce compilazione con:
inferred type arguments [_$1] do not conform to method apply's type parameter bounds [P <: Person[P]]
Lo stesso errore si verifica per un metodo con un argomento legato come:
def general[P <: Person[P]](p: P) = println(p)
quindi questo è non specifico per i costruttori di classi.
Due domande:
Il tipo
Person
è definita con limiti parametriPerson[+T <: Person[T]]
, in modo che ciascuna istanza di questo tipo è assicurato da rispettare i limiti:val p: Person[P]
implica cheP <: Person[P]
; O mi sta sfuggendo qualcosa? Quindi, come posso chiarirlo al compilatore in modo che non si lamenti?Come/Posso definire una classe case con membri con parametro tipo non associato come
case class University(p: Person[_])
?
Il 'T' deve essere covariante? – leedm777
@dave nel mio caso particolare 'T' deve essere covariante, ma penso che questo non cambi il problema: vedi l'esempio introduttivo. –
Si potrebbe ottenere da qualche parte usando [tipi astratti] (http://docs.scala-lang.org/tutorials/tour/abstract-types.html), ma poi diventano [praticamente invarianti] (http: // stackoverflow. com/a/5359015/115478). – leedm777