Domanda

Sto cercando di capire il significato esatto delle parole Covariance e Contravariance di diversi articoli on-line e le domande su StackOverflow, e da quello che posso capire, è solo un'altra parola per il polimorfismo .

Sono corretto con la dichiarazione di cui sopra? Oppure ho capito male?

È stato utile?

Soluzione

E 'certamente legato al polimorfismo. Non direi che sono solo "un'altra parola" per il polimorfismo però - sono di situazioni molto specifiche, in cui è possibile trattare un tipo come se fosse un altro tipo in un certo contesto <. / p>

Per esempio, con il polimorfismo normale è possibile trattare qualsiasi riferimento ad un Banana come un riferimento a un Fruit - ma questo non significa che è possibile sostituire List<Banana> tutti volta che si vedere il tipo List<Fruit>. Ad esempio, un list.Add(new Apple()) non può essere trattato come un <=> perché <=> vale per <=> ma non per <=>.

covarianza consente una "grande" (meno specifico) tipo da sostituire in un'API cui il tipo di originale è solo utilizzato in posizione di "uscita" (ad esempio come valore di ritorno). Controvarianza permette un "piccolo" (più preciso) tipo da sostituire in un'API cui il tipo di originale è solo utilizzato in posizione di "ingresso".

E 'difficile entrare in tutti i dettagli in un post unico SO (anche se si spera che qualcun altro farà un lavoro migliore di questo!). Eric Lippert ha un eccellente su di esso.

Altri suggerimenti

Grazie per tutti i messaggio-out, ragazzi.

risposte

Jon e Rasmus di vanno bene, vorrei solo aggiungere una nota tecnica rapida.

Quando si parla con disinvoltura e in modo informale, sì, la gente usa "covarianza" e "controvarianza" per riferirsi a uno specifico tipo di polimorfismo. Cioè, il tipo di polimorfismo in cui si trattano una sequenza di ragni, come se si trattasse di una sequenza di animali.

Se dovessimo ottenere tutti i computer-sciency e cerchiamo di rendere le definizioni più tecnici, allora probabilmente non direi che covarianza e controvarianza sono "una sorta di polimorfismo". Vorrei affrontare una definizione più tecnica in questo modo:

In primo luogo, vorrei notare che ci sono due possibili tipi di polimorfismo in C # che si potrebbe parlare di, ed è importante non li confondere.

Il primo tipo è tradizionalmente chiamato "polimorfismo ad hoc", e questo è il polimorfismo in cui si dispone di un metodo M (Animale x), e si passa ragni e giraffe e wallaby ad esso, e il metodo considera uniformemente il suo passato-in argomenti allo stesso modo utilizzando i punti in comune garantiti dalla classe di base degli animali.

Il secondo tipo è tradizionalmente chiamato "il polimorfismo parametrico", o "il polimorfismo generico". Questa è la capacità di fare un metodo generico M<T>(T t) e quindi avere un po 'di codice nel metodo che ancora una volta, tratta l'argomento in maniera uniforme sulla base di elementi comuni garantiti dai vincoli su T.

Credo che tu stia parlando del primo tipo di polimorfismo. Ma il mio punto è proprio che possiamo definire il polimorfismo come la capacità di un linguaggio di programmazione per il trattamento di diverse cose in modo uniforme sulla base di una comunanza noto. (Ad esempio, un noto tipo di base, o conosciuto interfaccia implementata.)

Covarianza e controvarianza è la capacità di un linguaggio di programmazione per sfruttare in comune tra i tipi generici dedotte da comunanze note dei loro argomenti di tipo.

È possibile pensare a co- e controvarianza come una forma avanzata di polimorfismo. Non solo è possibile utilizzare un bambino di classe come se fosse il suo genitore di classe, con co- e controvarianza, il polimorfismo si estende alle classi che si riferisce alle classi polimorfiche.

Immaginate due classi:

public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }

Il polimorfismo è in grado di utilizzare un Cat come Pet:

void Feed(Pet pet) { /* ... */ }

Cat cat = ...
Feed(cat);

Co- e controvarianza è usato per parlare di essere in grado di utilizzare un ICollection<Cat> come ICollection<Pet> (covarianza):

void FeedAll(ICollection<Pet> pets) { /* ... */ }

List<Cat> cats = ...
FeedAll(cats);

o di utilizzare un Action<Pet> come Action<Cat> (controvarianza):

Action<Pet> GetFeeder() { /* ... */ }

Action<Cat> feeder = GetFeeder();

Eric Lippert ha scritto una grande serie di blog su di esso quando sono stati progettando la funzione. La prima parte è qui .

credo sia è speciale tipo di polimorfismo non un'altra parola per esso. Si tratta di polimorfismo in delegati in cui un delegato con un tipo di ritorno della base può accettare tipo bambino.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top