2009-07-03 9 views

Respuesta

62

Ciertamente está relacionado con el polimorfismo. Sin embargo, no diría que son solo "otra palabra" para el polimorfismo: se trata de situaciones muy específicas, donde puedes tratar un tipo como si fuera otro tipo en un contexto determinado.

Por ejemplo, con el polimorfismo normal, se puede tratar cualquier referencia a un Banana como una referencia a un Fruit - pero eso no significa que se puede sustituir Fruit cada vez que vea el tipo Banana. Por ejemplo, un List<Banana> no se puede tratar como List<Fruit> porque list.Add(new Apple()) es válido para List<Fruit> pero no para List<Banana>.

Covarianza permite un "más grande" (menos específico) tipo que ser sustituido en una API donde el tipo original es solamente utilizado en una posición "de salida" (por ejemplo, como un valor de retorno). La contradicción permite que un tipo "más pequeño" (más específico) sea sustituido en una API donde el tipo original es solo usado en una posición de "entrada".

Es difícil entrar en todos los detalles en una sola publicación de SO (aunque espero que alguien más haga un mejor trabajo que esto). Eric Lippert tiene un excelente series of blog posts al respecto.

+0

Ah, sí de hecho estaba leyendo mensajes de Lippert, y los encontró q uite helpful –

+0

Las publicaciones del blog fueron todas publicadas en octubre de 2007, creo, así que están disponibles en esta página: http://blogs.msdn.com/ericlippert/archive/2007/10.aspx –

+0

No, había otra en la serie muy recientemente ("The void is invariant") –

-2

Creo que es un tipo especial de polimorfismo, no otra palabra para describirlo. Es polimorfismo en delegados donde un delegado con un tipo de base de retorno puede aceptar el tipo de niño.

+1

no es aspectos del polimorfismo en los parámetros de función y los valores de retorno. esto significa que afecta a los delegados pero no los requiere – ShuggyCoUk

16

Puede pensar en co y contravariancia como una forma avanzada de polimorfismo. No solo puedes usar una clase hija como si fuera su clase padre, con co y contravariancia, el polimorfismo se extiende a las clases que se relacionan con las clases polimórficas.

Imaginemos dos clases:

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

El polimorfismo es ser capaz de utilizar un Cat como Pet:

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

Cat cat = ... 
Feed(cat); 

Cooperación y contravarianza se utiliza para hablar de ser capaz de utilizar un ICollection<Cat> como un ICollection<Pet> (covarianza):

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

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

o utilizar un Action<Pet> como Action<Cat> (contravarianza):

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

Action<Cat> feeder = GetFeeder(); 

Eric Lippert escribió una gran serie blog sobre él cuando estaban diseñando primero la función. La primera parte es here.

+0

En su ejemplo de covarianza, ¿no debería ser 'nulo FeedAll (ICollection pets)' en lugar de 'ICollection '? –

+0

@Ray Gracias. Fijo. –

+0

Me gusta más tu publicación .... más ejemplos de color y código. Me gustan las imágenes bonitas;) Entonces 'CoVariance' se evalúa por herencia y' ContraVariance' se evalúa de la otra manera ... como en 'Contradictory'? – GoldBishop

39

Gracias por todos los gritos, muchachos.

Las respuestas de Jon y Rasmus están bien, solo agregaría una nota técnica rápida.

Cuando se habla casualmente e informalmente, sí, las personas usan "covarianza" y "contravarianza" para referirse a un tipo específico de polimorfismo. Es decir, el tipo de polimorfismo en el que se trata una secuencia de arañas como si fuera una secuencia de animales.

Si tuviéramos que obtener todas las ciencias de la computación y tratar de hacer más definiciones técnicas, entonces probablemente no diría que la covarianza y la contravarianza son "una especie de polimorfismo". Me acercaría a una definición más técnica como esta:

Primero, señalaría que hay dos tipos posibles de polimorfismo en C# de los que podría estar hablando, y es importante no confundirlos.

El primer tipo se denomina tradicionalmente "polimorfismo ad hoc", y ese es el polimorfismo en el que tienes un método M (Animal x), y pasas arañas y jirafas y wallabies hacia él, y el método trata uniformemente su pasado. en argumentos de la misma manera mediante el uso de las similitudes garantizadas por la clase base Animal.

El segundo tipo se denomina tradicionalmente "polimorfismo paramétrico" o "polimorfismo genérico". Esa es la capacidad de hacer un método genérico M<T>(T t) y luego tener un montón de código en el método que otra vez, trata el argumento de manera uniforme sobre la base de elementos comunes garantizados por las restricciones sobre T.

Creo que estás hablando de la primera clase de polimorfismo. Pero mi punto es que podemos definir el polimorfismo como la capacidad de un lenguaje de programación para tratar diferentes cosas de manera uniforme en función de una característica común conocida. (Por ejemplo, un conocido tipo de base, o interfaz implementada conocida.)

Covarianza y contravarianza es la capacidad de un lenguaje de programación para toma ventaja de puntos en común entre los tipos genéricos deducidas a partir de elementos comunes conocidas de sus argumentos de tipo.

+0

entonces, ¿sería correcto decir que la varianza (co | contra) son mecanismos por los cuales se logra polimorfismo? – iliketocode

+0

@EricLippert ... ASÍ QUE LO QUE DIGAS ES ... es polimórfico en el nivel genérico pero no polimórfico en el nivel específico;) Digo que llueve Gatos y Perros siempre que 'Lluvia (T: Animal)' – GoldBishop

12
+0

yup esa es la colección de Lippert –

Cuestiones relacionadas