Quelqu'un peut-il m'expliquer, le concept de covariance et contravariance dans la théorie des langages de programmation?Covariance et contravariance dans les langages de programmation
Répondre
Covariance est assez simple et la meilleure idée de la perspective d'une classe de collection List
. Nous pouvons paramétrer la classe List
avec un paramètre de type T
. Autrement dit, notre liste contient des éléments de type T
pour certains T
. Liste serait Covariant si
S est un sous-type de liste T ssi [S] est un sous-type de liste [T]
(où j'utilise la définition mathématique ssi signifie si et seulement si.)
C'est un List[Apple]
est unList[Fruit]
. S'il y a une routine qui accepte un List[Fruit]
comme paramètre, et que j'ai un List[Apple]
, alors je peux le passer en paramètre valide.
def something(l: List[Fruit]) {
l.add(new Pear())
}
Si notre classe de collection List
est mutable, alors covariance n'a pas de sens, car on peut supposer que notre routine pourrait ajouter un autre fruit (qui n'a pas été une pomme) comme ci-dessus. Par conséquent, nous devrions seulement aimer immutables classes de collecte pour être covariant!
Bonne définition, mais il manque le fait que non seulement les types peuvent être traités comme co/contravariant. Par exemple, Java 'List
Je crois que 'List extends Fruit> 'est une sorte de * type existentiel *: c'est-à-dire' List [T] forSome T <: Fruit' - le * forSome T <: Fruit * est lui-même un type dans cette instance. Java n'est toujours pas covariant dans ce type. Par exemple une méthode acceptant un 'List extends Fruit> 'ne pas accepter' List étend Fruit> ' –
Je veux dire" n'accepterait pas un 'Liste étend Apple>' bien sûr –
Ceci est une bonne explication, pas bookish.Merci –
Heck - J'ai même apprécié de le lire.Plus de Wikipedia :) – xtofl
Eh bien FWIW, l'explication provient d'une discussion que mes collègues et moi avons eue avec un membre éminent (ancien HP) lorsque la discussion a tourné vers OOSC par Bertrand Meyers dans laquelle je pense que Meyers souligne l'importance de la contravariance dans OOP. – Abhay
Voici mes articles sur la façon dont nous avons ajouté de nouvelles fonctionnalités variance à 4,0 C#. Commencez par le bas.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
OT: Eric, vous avez posté un puzzle sur l'une des questions plus tôt. Je n'ai pas pu le résoudre et j'ai posé des questions à ce sujet. Pourriez-vous s'il vous plaît le regarder? http://stackoverflow.com/questions/1167666/c-puzzle-reachable-goto-pointing-to-an-unreachable-label – SolutionYogi
OMG Eric Lippert !!!! – Janie
Regardez-le avec ces points d'exclamation. Vous pouvez mettre un oeil sur quelqu'un avec une de ces choses. –
Bart De Smet a une grande entrée de blog sur la covariance & contravariance here.
Pour plus de commodité, voici une liste ordonnée de liens vers tous les articles de Eric Lippert sur les écarts:
- Covariance and Contravariance in C#, Part One
- Covariance and Contravariance in C#, Part Two: Array Covariance
- Covariance and Contravariance in C#, Part Three: Method Group Conversion Variance
- Covariance and Contravariance in C#, Part Four: Real Delegate Variance
- Covariance and Contravariance In C#, Part Five: Higher Order Functions Hurt My Brain
- Covariance and Contravariance in C#, Part Six: Interface Variance
- Covariance and Contravariance in C# Part Seven: Why Do We Need A Syntax At All?
- Covariance and Contravariance in C#, Part Eight: Syntax Options
- Covariance and Contravariance in C#, Part Nine: Breaking Changes
- Covariance and Contravariance in C#, Part Ten: Dealing With Ambiguity
Il y a une distinction faite entre covariance et contravariance.
Très grossièrement, une opération est covariante si elle préserve l'ordre des types, et contravariante si elle inverse cet ordre.
La commande elle-même est destinée à représenter des types plus généraux plus grands que des types plus spécifiques.
Voici un exemple d'une situation où C# supporte la covariance. Tout d'abord, c'est un tableau d'objets:
object[] objects=new object[3];
objects[0]=new object();
objects[1]="Just a string";
objects[2]=10;
Bien sûr, il est possible d'insérer des valeurs différentes dans le tableau, car à la fin, ils dérivent tous System.Object
dans framework .Net. En d'autres termes, System.Object
est un type très général ou grand. Maintenant, voici un endroit où covariance est prise en charge:
attribution d'une valeur d'un type plus petit à une variable d'un type plus grand
string[] strings=new string[] { "one", "two", "three" };
objects=strings;
Les objets variables, qui est de type object[]
, peut stocker une valeur c'est en fait de type string[]
. Pensez-y - jusqu'à un certain point, c'est ce que vous attendez, mais ce n'est pas le cas. Après tout, alors que string
dérive de object
, string[]
NE DÉCRIT PAS dérive de object[]
. Le support de la langue pour la covariance dans cet exemple rend l'assignation possible de toute façon, ce que vous trouverez dans de nombreux cas. La variante est une fonctionnalité qui rend le langage plus intuitif.
Les considérations autour de ces sujets sont extrêmement compliquées. Par exemple, en fonction du code précédent, voici deux scénarios qui entraîneront des erreurs. Un exemple pour le fonctionnement de la contravariance est un peu plus compliqué.Imaginez ces deux classes:
public partial class Person: IPerson {
public Person() {
}
}
public partial class Woman: Person {
public Woman() {
}
}
Woman
est dérivé de Person
, évidemment. Considérons maintenant que vous avez ces deux fonctions:
static void WorkWithPerson(Person person) {
}
static void WorkWithWoman(Woman woman) {
}
L'une des fonctions fait quelque chose (peu importe quoi) avec un Woman
, l'autre est plus générale et peut fonctionner avec tout type dérivé de Person
. Du côté Woman
des choses, vous avez maintenant également:
delegate void AcceptWomanDelegate(Woman person);
static void DoWork(Woman woman, AcceptWomanDelegate acceptWoman) {
acceptWoman(woman);
}
DoWork
est une fonction qui peut prendre un Woman
et une référence à une fonction qui prend aussi un Woman
, puis il passe l'instance de Woman
à le délégué. Considérez le polymorphisme des éléments que vous avez ici. Person
est plus grand que Woman
, et WorkWithPerson
est plus grand que WorkWithWoman
. WorkWithPerson
est également considéré plus grand que AcceptWomanDelegate
à des fins de variance.
Enfin, vous avez ces trois lignes de code:
Woman woman=new Woman();
DoWork(woman, WorkWithWoman);
DoWork(woman, WorkWithPerson);
Une instance Woman
est créé. Puis DoWork est appelé, en passant dans l'instance Woman
ainsi qu'une référence à la méthode WorkWithWoman
. Ce dernier est évidemment compatible avec le type de délégué AcceptWomanDelegate
- un paramètre de type Woman
, aucun type de retour. La troisième ligne est un peu étrange, cependant. La méthode WorkWithPerson
prend un Person
comme paramètre, pas un Woman
, comme requis par AcceptWomanDelegate
. Néanmoins, WorkWithPerson
est compatible avec le type délégué. Contravariance permet, dans le cas de délégués le plus grand type WorkWithPerson
peut être stocké dans une variable du plus petit type AcceptWomanDelegate
. Une fois de plus c'est la chose intuitive: si WorkWithPerson
peut fonctionner avec n'importe quel Person
, passant dans un Woman
ne peut pas se tromper, non? À l'heure actuelle, vous vous demandez peut-être comment tout cela se rapporte aux génériques. La réponse est que la variance peut aussi être appliquée aux génériques. L'exemple précédent utilise les tableaux object
et string
. Ici, le code utilise des listes génériques au lieu des tableaux:
List<object> objectList=new List<object>();
List<string> stringList=new List<string>();
objectList=stringList;
Si vous essayez ceci, vous constaterez que ce n'est pas un scénario pris en charge en C#. En C# version 4.0 ainsi que NET Framework 4.0, le soutien de la variance des génériques a été nettoyé, et il est maintenant possible d'utiliser les nouveaux mots-clés dans et sur avec des paramètres de type générique. Ils peuvent définir et restreindre la direction du flux de données pour un paramètre de type particulier, permettant à la variance de fonctionner.Mais dans le cas de List<T>
, les données de type T
circulent dans les deux sens - il existe des méthodes sur le type List<T>
qui renvoient des valeurs T
, et d'autres qui reçoivent de telles valeurs.
Le point de ces restrictions directionnelles est pour permettre la variance où il est logique, mais pour éviter les problèmes comme l'erreur d'exécution mentionné dans l'un des exemples précédents du tableau. Lorsque les paramètres de type sont décorées correctement dans ou sur, le compilateur peut vérifier, et autoriser ou non, sa variance à temps compilation. Microsoft est allé à l'effort d'ajouter ces mots-clés à de nombreuses interfaces standard dans framework .Net, comme IEnumerable<T>
:
public interface IEnumerable<out T>: IEnumerable {
// ...
}
Pour cette interface, le flux de données de type T
objets est clair: ils ne peuvent jamais être récupérées à partir des méthodes prises en charge par cette interface, qui ne leur ont pas été transmises. En conséquence, il est possible de construire un exemple similaire à la List<T>
tentative décrite précédemment, mais en utilisant IEnumerable<T>
:
IEnumerable<object> objectSequence=new List<object>();
IEnumerable<string> stringSequence=new List<string>();
objectSequence=stringSequence;
Ce code est acceptable pour le compilateur C# depuis la version 4.0, car IEnumerable<T>
est covariante en raison de la sur spécificateur sur le paramètre de type T
. Lorsque vous travaillez avec des types génériques, il est important d'être conscient de la variance et de la manière dont le compilateur applique différents types de tromperie pour que votre code fonctionne comme vous le souhaitez.
Il y a plus à connaître sur la variance que ce qui est couvert dans ce chapitre, mais cela suffira pour rendre tout autre code compréhensible.
Ref:
C# et le CLR permettent de covariance et contre-variance des types de référence lorsque liant une méthode à un délégué. Covariance signifie qu'une méthode peut renvoyer un type dérivé du type de retour du délégué. La contra-variance signifie qu'une méthode peut prendre un paramètre qui est une base du type de paramètre du délégué. Par exemple, étant donné qu'un délégué est défini comme suit:
delegate Object MyCallback (FileStream s);
il est possible de construire une instance de ce type délégué lié à une méthode qui est prototypée
comme ceci:
Chaîne SomeMethod (courant s);
Ici, le type de retour de SomeMethod (String) est un type dérivé du type de retour du délégué (Object); cette covariance est autorisée.Le type de paramètre de SomeMethod (Stream) est un type qui est une classe de base du type de paramètre du délégué (FileStream); cette contre-variance est autorisée.
Notez que la covariance et la contre-variance sont prises en charge uniquement pour les types de référence, pas pour les types de valeur ou pour les vides. Ainsi, par exemple, je ne peux pas lier la méthode suivante au délégué MyCallback:
Int32 SomeOtherMethod (Streams);
Même si le type de retour de SomeOtherMethod (Int32) est dérivé du type retour de MyCallback (Object), cette forme de covariance n'est pas autorisé parce que Int32 est un type de valeur.
De toute évidence, la raison pour laquelle les types de valeur et non avenue ne peuvent pas être utilisés pour covariance et contre-variance est parce que la structure de mémoire pour ces choses varie, alors que la structure de la mémoire pour les types de référence est toujours un pointeur. Heureusement, le compilateur C# produira une erreur si vous essayez de faire quelque chose qui n'est pas supporté.
- 1. Langages de programmation SIMD
- 2. gVim et plusieurs langages de programmation
- 3. Référence de fonctions similaires entre les langages de programmation
- 4. .net règles de covariance dans les génériques
- 5. Gestion de projets concurrents écrits dans différents langages de programmation
- 6. Méthodes d'effets secondaires dans purement langages de programmation fonctionnelle
- 7. La contravariance des événements et des délégués dans .NET 4.0 et C# 4.0
- 8. Java covariance
- 9. Utilisation de NetBeans pour plusieurs langages de programmation
- 10. Bases de données relationnelles et langages OO
- 11. Quels langages de programmation puis-je coder et compiler à partir de ma clé USB?
- 12. Compression et décompression en java ne fonctionne pas bien pour différents langages de programmation
- 13. Quelle est la différence de vitesse entre les langages DLR et C# dans Silverlight 2?
- 14. Comment effectuer des tests de performance sur des bibliothèques écrites dans différents langages de programmation?
- 15. Est-ce que des concepts comme Map et Reduce s'appliquent à tous les langages de programmation fonctionnelle?
- 16. Intégration d'applications utilisant plusieurs langages de programmation dans une application Java
- 17. Connaissez-vous un bon guide de référence rapide pour un certain nombre de langages de programmation?
- 18. Quelles langues prennent en charge la covariance sur les types de retour des méthodes héritées?
- 19. La contravariance semble provoquer un comportement confus
- 20. Implémentations de liaison dynamique dans les langages OO
- 21. Quelles sont les meilleures pratiques pour la programmation fonctionnelle et l'interaction avec les bases de données?
- 22. Existe-t-il des langages de programmation conçus pour utiliser uniquement la voix pour l'entrée?
- 23. Préférez-vous les langages compilés ou scriptés?
- 24. Comment/pourquoi les langages fonctionnels (en particulier Erlang) s'adaptent bien?
- 25. Dans quelles circonstances les langages dynamiques sont-ils appropriés?
- 26. Diagramme de méthodologie de programmation?
- 27. Comment l'allocation de mémoire est-elle effectuée pour les variables dans les langages de script?
- 28. Existe-t-il un moyen de transmettre la covariance?
- 29. Schémas de mise en cache pour les langages gérés
- 30. Quelles sont les plus grandes erreurs de conception dans les langages ou bibliothèques populaires?
Je sens une question de devoirs. –
[covariance vs contravariance] (http://izlooite.blogspot.com/2011/04/covariance-and-contravariance.html) –
duplication possible de [C#: Variance (Covariance/Contravariance) un autre mot pour polymorphisme?] (http://stackoverflow.com/questions/1078423/c-sharp-is-variance-covariance-contravariance-another-word-for-polymorphis) – nawfal