Ho appena imparato Scala. Ora sono confuso riguardo la controvarianza e la covarianza.Contravarianza vs Covarianza in Scala
Da questo page, ho imparato qualcosa di seguito:
covarianza
Forse la caratteristica più evidente di sottotipo è la possibilità di sostituire un valore di un tipo più ampio con un valore di un tipo più stretta in un'espressione . Ad esempio, supponiamo di avere alcuni tipi Real
, Integer <: Real
e alcuni tipi non collegati Boolean
. Posso definire una funzione is_positive :: Real -> Boolean
che funziona sui valori Real
, ma posso anche applicare questa funzione ai valori di tipo Integer
(o qualsiasi altro sottotipo di Real
). Questa sostituzione di tipi più ampi (antenati) con tipi più stretti (discendenti) è denominata covariance
. Il concetto di covariance
ci consente di scrivere codice generico ed è inestimabile quando ragioniamo sull'ereditarietà nei linguaggi di programmazione orientata agli oggetti e sul polimorfismo nei linguaggi funzionali.
Tuttavia, ho anche visto qualcosa da qualche altra parte:
scala> class Animal
defined class Animal
scala> class Dog extends Animal
defined class Dog
scala> class Beagle extends Dog
defined class Beagle
scala> def foo(x: List[Dog]) = x
foo: (x: List[Dog])List[Dog] // Given a List[Dog], just returns it
scala> val an: List[Animal] = foo(List(new Beagle))
an: List[Animal] = List([email protected])
Parametro x
di foo
è contravariant
; si aspetta un argomento di tipo List[Dog]
, ma gli diamo un List[Beagle]
, e va bene
[Quello che penso sia il secondo esempio dovrebbe anche provare Covariance
. Perché dal primo esempio ho appreso che "applica questa funzione ai valori di tipo Integer
(o qualsiasi altro sottotipo di Real
)". Quindi, corrispondentemente, qui si applica questa funzione ai valori di tipo List[Beagle]
(o qualsiasi altro sottotipo di List[Dog]
). Ma con mia sorpresa, il secondo esempio dimostra Cotravariance
]
Penso che due stiano parlando la stessa cosa, ma uno dimostra Covariance
e l'altro Contravariance
. Ho anche visto this question from SO. Tuttavia sono ancora confuso. Ho perso qualcosa o uno degli esempi è sbagliato?
Buona spiegazione. Il tipo di ritorno di 'groomAnyAnimal' dovrebbe essere' Dog' per collegarlo, dato che le funzioni sono covarianti nel loro tipo di ritorno e controvarianti solo nel loro tipo di argomento. –
@stew quindi pensi che le dichiarazioni del secondo esempio siano in qualche modo sbagliate? – CSnerd
@CSnerd Nel tuo secondo esempio, in qualche modo vuoi fare una dichiarazione sul fatto che 'x' sia covariante o controverso. Tuttavia, come menzionato lo stufato, la varianza non ha nulla a che fare se si riesce a passare un sottotipo in cui è richiesto un supertipo (si veda [Principio di sostituzione di Liskov] (http://en.wikipedia.org/wiki/Liskov_substitution_principle)). L'unica cosa covariante nel tuo secondo esempio è 'List', quindi' List [Beagle] 'è un sottotipo di' List [Dog] '. –