2011-12-12 13 views

Respuesta

17

No puede tener var de tipo covariante. Una var equivale a tener, entre otras cosas, un def v_=(newV: T) público, por lo que hace que T aparezca como un argumento de rutina, que es una posición contravariante. Por lo que debe o bien

  • renuncia covarianza y declarar C [T] en lugar de C [+ T]
  • maquillaje va val

Para ser un poco más detallado en el "por qué" parte de su pregunta, al hacer T es el parámetro covariante con + T, declara que quiere que C [B] sea un subtipo de C [A] si B es un subtipo de A. Esto significa que desea permitir:

val cb: C[B] = new C[B] 
val ca : C[A] = cb  

Para hace que suene, el compilador restringe dónde T puede aparecer en C. Para hacerlo breve y con pequeñas simplificaciones, v no puede aparecer como parámetro de una rutina (o como el tipo de una var). De lo contrario, después de haber inicializado CB y CA como se describió anteriormente que coulddo

ca.v = new A 

Esto se permitiría, como ca se supone que es un C[A], por lo que su variable v es de tipo A. Sin embargo, como C es covariante en T, ca puede (y lo hace en el ejemplo) hacer referencia a una instancia C[B]. Se permitiría esta asignación, entonces podría hacer

val vInCb: B = cb.v 

seguros de que esto le da una B. Sin embargo, usted acaba de poner un A allí a través de la referencia ca. Esta situación debe estar prohibida, y lo es, al prohibir el parámetro de tipo covariante T como el tipo de una var.

+0

Hay una tercera opción ... –

+0

Muchas gracias Daniel, había escrito una tercera variante con privacidad y la quité después de las pruebas, me había olvidado de esto [esto] –

2

Tienes que hacerlo un val. A var siempre tiene un método setter donde el tipo aparece en una posición contravariante.

9

Se puede declarar como private[this]:

class C [+T] { private[this] var v : T = _ } 

Cualquier uso intenta que este ámbito no permite que sería insegura con un co-variante T.

Cuestiones relacionadas