C# :¿Es Varianza (Covarianza/Contravarianza) otra palabra para Polimorfismo?
-
21-08-2019 - |
Pregunta
Estoy tratando de descubrir el significado exacto de las palabras. Covariance
y Contravariance
de varios artículos en línea y preguntas sobre StackOverflow, y por lo que puedo entender, es solo otra palabra para polimorfismo.
¿Estoy en lo cierto con la afirmación anterior?¿O me he equivocado?
Solución
Es ciertamente relacionado con el polimorfismo. Yo no diría que son sólo "otra palabra" para el polimorfismo sin embargo - que están a punto situaciones muy específicas, donde se puede tratar a un tipo como si fuera otro tipo en un determinado contexto <. / p>
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 List<Banana>
todos vez que se ver el tipo List<Fruit>
. Por ejemplo, un list.Add(new Apple())
no puede ser tratado como un <=> porque <=> es válido para <=> pero no para <=>.
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). Contravarianza permite un "más pequeño" (más específico) tipo que ser sustituido en una API donde el tipo original es solamente utilizado en una posición "de entrada".
Es difícil entrar en todos los detalles en un solo puesto SO (aunque es de esperar que alguien más va a hacer un trabajo mejor que esto!). Eric Lippert tiene una excelente serie rel="noreferrer"> al respecto.
Otros consejos
Gracias por todos los agradecimientos, chicos.
Las respuestas de Jon y Rasmus están bien, solo agregaría una nota técnica rápida.
Cuando se habla de manera casual e informal, sí, la gente usa "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 nos centráramos exclusivamente en la informática y tratáramos de hacer definiciones más 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, quisiera señalar 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 llama tradicionalmente "polimorfismo ad hoc", y ese es el polimorfismo en el que tienes un método M(Animal x), y le pasas arañas, jirafas y ualabíes, y el método trata uniformemente los argumentos pasados de la misma manera. manera utilizando los puntos en común garantizados por la clase base Animal.
El segundo tipo se denomina tradicionalmente "polimorfismo paramétrico" o "polimorfismo genérico".Esa es la capacidad de crear un método genérico. M<T>(T t)
y luego tener un montón de código en el método que nuevamente trata el argumento de manera uniforme en función de los puntos en común garantizados por las restricciones de T.
Creo que estás hablando del primer tipo de polimorfismo.Pero mi punto es simplemente que podemos definir el polimorfismo como la capacidad de un lenguaje de programación para Tratar diferentes cosas de manera uniforme basándose en una característica común conocida. (Por ejemplo, un tipo base conocido o una interfaz implementada conocida).
Covarianza y contravarianza es la capacidad de un lenguaje de programación para aprovechar los puntos en común entre tipos genéricos deducidos de los puntos en común conocidos de sus argumentos de tipo.
Puede pensar co- y contravarianza como una forma avanzada de polimorfismo. No sólo se puede utilizar una clase niño como si fuera su clase padre, la cooperación y contravarianza, el polimorfismo se extiende a las clases que se relaciona con las clases polimórficas.
Imaginemos dos clases:
public class Pet { /*...*/ }
public class Cat:Pet { /*...*/ }
polimorfismo es ser capaz de utilizar un Cat
como un Pet
:
void Feed(Pet pet) { /* ... */ }
Cat cat = ...
Feed(cat);
Co- y contravarianza se usa 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 un 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 aquí .
He encontrado esta colección:
covarianza y contravarianza en C #, primera parte
Covarianza y contravarianza en C #, Segunda parte: de covarianza de matriz
Covarianza y contravarianza en C #, Tercera parte: miembro Grupo Conversión varianza
Covarianza y contravarianza en C #, Cuarta parte: varianza real Delegado
Covarianza y contravarianza En C #, Quinta parte: funciones de orden superior Hurt mi cerebro
Covarianza y contravarianza en C #, Sexta parte: interfaz de varianza
Covarianza y contravarianza en C # Parte Siete: ¿por qué necesitamos una sintaxis en absoluto
?Covarianza y contravarianza en C #, pieza ocho: sintaxis Opciones
Covarianza y contravarianza en C #, Parte Nueve: Breaking Cambios
Covarianza y contravarianza en C #, Parte Ten: problema de la ambigüedad
Covarianza y contravarianza, Parte Once: Hasta el infinito, pero no más allá
Creo que es es tipo especial de polimorfismo no otra palabra para ello. Es polimorfismo en delegados donde un delegado con un tipo de retorno de la base puede aceptar el tipo de niños.