2012-06-30 17 views
14
scala> class C 
defined class C 

scala> class subC extends C 
defined class subC 

scala> class A { type T = C} 
defined class A 

scala> class subA extends A { override type T = subC} 
<console>:10: error: overriding type T in class A, which equals C; 
type T has incompatible type 
     class subA extends A { override type T = subC} 
             ^

Nell'esempio di cui sopra, ricevo un messaggio di errore, che non posso ignorare il campo Tipo in classe A (anche se il tipo scelto subC estende la classe C).È possibile sovrascrivere un campo tipo?

È possibile ignorare un campo di testo? E se sì, cosa c'è di sbagliato nell'esempio sopra?

risposta

22

Non si parlerà di "sovrascrittura" per quanto riguarda i tipi, ma piuttosto restringimento dei limiti.

  1. type T ... limiti
  2. type T <: C ... T è C o un sottotipo di C (che è chiamato limite superiore)
  3. type T >: C ... T è C o un supertipo di C (che è chiamato limite inferiore)
  4. type T = C ... T è esattamente C (tipo alias)

Pertanto, se T è un membro tipo di tratto A, e SubA è un sottotipo di A, nel caso (2) SubA possono restringere T ad una più particolare sottotipo C, mentre nel caso (3) si potrebbe restringere a un supertipo superiore di C. Il caso (1) non impone alcuna restrizione per SubA, mentre il caso (4) significa che T è "finale" per così dire.


Ciò incide l'utilizzabilità di T in A -se può apparire come tipo metodo dell'argomento o tipo di ritorno del metodo.

Esempio:

trait C { def foo =() } 
trait SubC extends C { def bar =() } 

trait MayNarrow1 { 
    type T <: C // allows contravariant positions in MayNarrow1 
    def m(t: T): Unit = t.foo // ...like this 
} 

object Narrowed1 extends MayNarrow1 { 
    type T = SubC 
} 

object Narrowed2 extends MayNarrow1 { 
    type T = SubC 
    override def m(t: T): Unit = t.bar 
} 

È possibile definire metodo m in MayNarrow1 perché tipo T verifica in posizione contravariant (come tipo di metodo di argomento), quindi è ancora valida anche se T si restringe verso il basso in un sottotipo di MayNarrow1 (il corpo del metodo può trattare t come se fosse il tipo C).

Al contrario, type T = C corregge inevitabilmente T, che corrisponderebbe a un metodo final.Fissando T, può essere utilizzato in una posizione covariante (come tipo di ritorno di un metodo):

trait Fixed extends MayNarrow1 { 
    type T = C // make that T <: C to see that it won't compile 
    final def test: T = new C {} 
} 

Si può ora facilmente vedere che deve essere vietato ulteriormente 'esclusione' T:

trait Impossible extends Fixed { 
    override type T = SubC 

    test.bar // oops... 
} 

Per essere completa, qui è il caso meno comune di un limite inferiore:

trait MayNarrow2 { 
    type T >: SubC // allows covariant positions in MayNarrow2 
    def test: T = new SubC {} 
} 

object Narrowed3 extends MayNarrow2 { 
    type T = C 
    test.foo 
} 

object Narrowed4 extends MayNarrow2 { 
    type T = C 
    override def test: T = new C {} 
} 
+1

Nota: per la sottile differenza tra membri di tipo astratto con limiti rispetto ai parametri di tipo con annotazioni di varianza, vedere il post di Geoffrey Washburn in http://scala-programming-language.1934581.n4.nabble.com/Scala-type-override-td1943353 .html –

Problemi correlati