Access Keys:
Skip to content (Access Key - 0)

Cette page liste un ensemble d'articles ayant pour thème l'utilisation des Generics.

Généralités

Avant d'essayer de comprendre comment bien utiliser les Generics, il est important de comprendre la différence entre les tableaux et les Collections génériques.

  • Les tableaux sont des objets covariants : si SubType est une sous-classe de SuperType alors SubType[] est aussi un sous type de SuperType[].
  • Les Collections sont des objets invariants : si SubType est une sous-classe de SuperType alors Collection<SubType> n'est PAS un sous type de Collection<SuperType>.

De ce point de vue, on peut dire que l'utilisation des tableaux est plus flexible mais que, dans la réalité, l'utilisation des Generics permet d'écrire du code plus sûr. Ci-dessous, vous trouverez deux exemples de code illustrant ces propos :

La règle PECS

L'apparent manque de flexibilité des Generics peut être comblé par l'utilisation des wildcards. Joshua Bloch a proposé d'utiliser les wildcards sur les paramètres des méthodes représentant des consommateurs ou des producteurs. Il appelle cela la règle PECS.
La règle PECS se retient facilement de la manière suivante : Producer-Extends, Consumer-Super.
Plus clairement, cela siginifie que :

  • si le type du paramètre de la méthode est un generic de E et que la méthode est productrice de E, alors il faut utiliser <? extends E>
  • si le type du paramètre de la méthode est un generic de E et que la méthode est consommatrice de E, alors il faut utiliser <? super E>

Joshua Bloch justifie la règle PECS en se basant sur l'exemple suivant :

Il veut ajouter une méthode public void pushAll(Iterable<E> src) à son API.
Comme Iterable<SubE> n'est pas une sous-classe de Iterable<E>, cette méthode n'est pas flexible à l'utilisation.
En effet, le code ci-dessous ne compilera pas :

Pour rendre plus flexible l'utilisation de cette méthode et faire que le code précédent compile, il faut alors modifier la méthode en la déclarant comme ceci : public void pushAll(Iterable<? extends E> src)

Ensuite, Joshua Bloch souhaite ajouter la méthode public void popAll(Collection<E> dst). La déclaration de cette méthode souffre elle aussi d'un manque de flexibilité ne permettant pas au code suivant de compiler :

Dans ce cas, le paramètre de la méthode ne devrait pas être du type "Collection de E" mais plutôt "Collection de supertype de E". Il faut alors utiliser le mot clé super en déclarant la méthode de la manière suivante : public void popAll(Collection<? super E> dst)

Cet exemple montre comment utiliser correctement les wildcards. Encore une fois, les wildcards ne sont ici utilisés qu'au niveau des paramètres de méthode car ils permettent d'accroître la flexibilité du code client et car ils sont quasi invisibles au niveau du code client.
Côté client, si un utilisateur d'API doit réfléchir à l'utilisation de wildcards, alors c'est qu'il y a un problème de conception de l'API. C'est pourquoi il faut absolument éviter d'avoir des méthodes qui retournent un type contenant un wildcard car cela forcerait le code client à utiliser ce wildcard.

Adaptavist Theme Builder (4.2.3) Powered by Atlassian Confluence 3.5.5, the Enterprise Wiki