112 votes

Donnez des exemples de fonctions qui démontrent la covariance et la contravariance dans les cas de surcharge et de surcharge en Java.

Veuillez montrer un bon exemple de covariance et de contravariance en Java.

161voto

Hardcoded Points 2786

Covariance :

class Super {
  Object getSomething(){}
}
class Sub extends Super {
  String getSomething() {}
}

Sub#getSomething est covariant car il renvoie une sous-classe du type de retour de Super#getSomething (mais remplit le contrat de Super.getSomething()).

Contravariance

class Super{
  void doSomething(String parameter)
}
class Sub extends Super{
  void doSomething(Object parameter)
}

Sub#doSomething est contravariant parce qu'il prend un paramètre d'une superclasse du paramètre de Super#doSomething (mais, encore une fois, remplit le contrat de Super#doSomething)

Remarque : cet exemple ne fonctionne pas en Java. Le compilateur Java surchargerait et ne remplacerait pas la méthode doSomething()-. D'autres langages supportent ce style de contravariance.

Génériques

Cela est également possible pour les produits génériques :

List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;

Vous pouvez maintenant accéder à toutes les méthodes de covariantList qui ne prend pas de paramètre générique (car il doit soit quelque chose comme "extends Object"), mais les getters fonctionneront sans problème (car l'objet retourné sera toujours de type "Object").

L'inverse est vrai pour contravariantList : Vous pouvez accéder à toutes les méthodes avec des paramètres génériques (vous savez qu'il doit s'agir d'une superclasse de "String", vous pouvez donc toujours en passer un), mais pas de getters (le type retourné peut être de n'importe quelle autre superclasse de String).

81 votes

Le premier exemple de contravariance ne fonctionne pas en Java. doSomething() dans la classe Sub est une surcharge, pas une surcharge.

16 votes

En effet. Java ne prend pas en charge les arguments contravariants dans le sous-typage. Seule la covariance concerne les types de retour des méthodes (comme dans le premier exemple).

0 votes

Excellente réponse. La covariance me semble logique. Mais pourriez-vous m'indiquer un paragraphe dans JLS qui décrit la contravariance ? Pourquoi Sub.doSomething est invoqué ?

50voto

Yardena Points 1640

Co-variance : Iterable et Iterator. Il est presque toujours judicieux de définir une co-variante Iterable o Iterator . Iterator<? extends T> peut être utilisé de la même manière que Iterator<T> - le seul endroit où le paramètre de type apparaît est le type de retour de la fonction next de sorte que l'on peut sans risque la faire passer à la méthode T . Mais si vous avez S s'étend T , vous pouvez également assigner Iterator<S> à une variable de type Iterator<? extends T> . Par exemple, si vous définissez une méthode de recherche :

boolean find(Iterable<Object> where, Object what)

vous ne pourrez pas l'appeler avec List<Integer> y 5 Il est donc préférable de le définir comme suit

boolean find(Iterable<?> where, Object what)

Contre-variance : Comparateur. Il est presque toujours judicieux d'utiliser Comparator<? super T> parce qu'il peut être utilisé de la même manière que le Comparator<T> . Le paramètre de type n'apparaît qu'en tant que compare le type de paramètre de la méthode T peut lui être transmis en toute sécurité. Par exemple, si vous avez un DateComparator implements Comparator<java.util.Date> { ... } et que vous souhaitez trier un List<java.sql.Date> avec ce comparateur ( java.sql.Date est une sous-classe de java.util.Date ), vous pouvez faire avec :

<T> void sort(List<T> what, Comparator<? super T> how)

mais pas avec

<T> void sort(List<T> what, Comparator<T> how)

3voto

Emiswelt Points 1552

Vous trouverez des informations à ce sujet sur wikipedia :

http://en.wikipedia.org/wiki/Covariance_and_contravariance_(informatique)#Java

-7voto

extraneon Points 13362

Regardez le Principe de substitution de Liskov . En effet, si la classe B étend la classe A, vous devriez pouvoir utiliser une B chaque fois qu'une A est nécessaire.

8 votes

Cela ne répond pas à la question et est trompeur. Il serait tout à fait possible de concevoir un système de variantes qui rompe la correction sémantique et viole donc la PSL.

1 votes

Ce n'est pas le cas pour contra variant dire. super.doSomething("String") n'a pas pu être remplacée par sub.doSomething(Object) .

1 votes

Ce n'est pas la question

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X