2011-12-12 12 views

risposta

17

Non è possibile avere una var di un tipo covariante. Un var equivale ad avere, tra le altre cose, un pubblico def v_=(newV: T), quindi fa apparire T come un argomento di routine, che è una posizione controvariante. Così si deve o

  • rinuncia covarianza e dichiarare C [T], piuttosto che C [+ T]
  • make va val

Per essere un po 'più dettagliato sul "perché" parte di la tua domanda, rendendo T è il parametro covariante con + T, si informa che è vuole C [B] per aa sottotipo di C [a] se B è un sottotipo di A. Questo significa che si vuole consente:

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

Per far sembrare questo, il compilatore limita dove T può apparire in C. Per renderlo breve e con piccole semplificazioni, v non può apparire come parametro di una routine (o come il tipo di una var). In caso contrario, dopo aver inizializzato cb e CA come descritto sopra si coulddo

ca.v = new A 

Questo sarebbe consentito, come ca si suppone essere un C[A], quindi la sua variabile v è di tipo A. Tuttavia, poiché C è covariante in T, ca può (e fa nell'esempio) fare riferimento a un'istanza C[B]. Sarebbe questo incarico essere consentito, si potrebbe poi fare

val vInCb: B = cb.v 

fiducioso che questo ti dà una B. Tuttavia, è sufficiente inserire uno A tramite il riferimento ca. Questa situazione deve essere proibita, e lo è, vietando il parametro di tipo covariante T come il tipo di una var.

+0

C'è una terza opzione ... –

+0

Grazie mille Daniel, avevo scritto una terza variante con privato e rimosso dopo i test, avevo dimenticato il [questo] –

2

Devi renderlo un val. A var ha sempre un metodo setter in cui il tipo viene visualizzato in posizione contraria.

9

È possibile dichiarare come private[this]:

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

Qualsiasi utilizzo si tenta che questo ambito non consente sarebbe pericoloso con un co-variante T.

Problemi correlati