Génériques et collections typées en programmation objet

Informatique de gestion · Bachelor 3

Types paramétrés, bornes, invariance et collections sûres : écrire du code réutilisable et typé.

Introduction

Les génériques permettent d'écrire une classe ou une méthode une seule fois pour plusieurs types, tout en gardant la vérification de types à la compilation. Une List<Client> ne peut contenir que des clients : le compilateur refuse l'ajout d'une facture et supprime les conversions explicites risquées qui provoquaient des erreurs à l'exécution dans les premières versions de Java.

Au-delà des collections de la bibliothèque standard, on définit ses propres types paramétrés, par exemple un Repository<T> réutilisable pour toutes les entités d'une application de gestion, ou une méthode générique de tri. On peut restreindre le paramètre par une borne (T extends Comparable<T>) afin de pouvoir utiliser les opérations de la borne.

Les génériques introduisent aussi des subtilités : List<Client> n'est pas une List<Personne> même si Client hérite de Personne (invariance), ce qui motive les jokers. En Java, l'effacement de type supprime l'information de type à l'exécution, alors que C# la conserve.

Objectifs d'apprentissage

  • Définir une classe et une méthode génériques avec un ou plusieurs paramètres de type
  • Utiliser une borne pour exiger une capacité (comparabilité) sur le paramètre
  • Expliquer pourquoi List<Client> n'est pas un sous-type de List<Personne>
  • Choisir entre jokers extends et super selon qu'on lit ou qu'on écrit
  • Citer les limites des génériques liées à l'effacement de type en Java

Concepts clés

Type paramétré
Classe ou interface déclarée avec un paramètre de type (Boite<T>) instancié lors de l'utilisation (Boite<Facture>).
Borne
Contrainte sur le paramètre (T extends Comparable<T>) qui autorise l'usage des méthodes de la borne dans le code générique.
Invariance et jokers
Les types paramétrés sont invariants ; les jokers (? extends T pour lire, ? super T pour écrire) expriment une covariance ou contravariance contrôlée.
Effacement de type
En Java, les paramètres de type sont supprimés à la compilation : on ne peut pas faire new T() ni instanceof List<String>.

Conclusion

Les génériques sont l'outil qui permet de réutiliser sans sacrifier la sûreté de typage. Maîtriser les bornes et les jokers évite autant de copier-coller que d'erreurs de conversion à l'exécution.

Dans un projet de gestion, ils servent chaque jour : collections typées, dépôts de données génériques, utilitaires de tri. Comprendre l'invariance et l'effacement de type évite les surprises lors de la conception d'API réutilisables.

Cartes

Quel problème les génériques résolvent-ils ?
Ils offrent la réutilisation du code pour plusieurs types avec vérification statique, sans conversions explicites dangereuses.
Que signifie List<Client> ?
Une liste dont tous les éléments sont de type Client, ce que le compilateur vérifie.
Comment écrire une méthode générique qui retourne le maximum d'une liste ?
En déclarant un paramètre de type borné par Comparable : <T extends Comparable<T>> T max(List<T> liste).
Pourquoi List<Client> n'est-elle pas une List<Personne> ?
Si c'était permis, on pourrait y ajouter une Personne non Client : l'invariance protège contre cette violation de type.
Quand utiliser ? extends T ?
Quand on ne fait que lire dans la structure (producteur) : on obtient des T mais on ne peut pas y ajouter d'éléments.
Quand utiliser ? super T ?
Quand on ne fait qu'écrire dans la structure (consommateur) : on peut y ajouter des T mais on lit seulement des Object.
Que provoque l'effacement de type en Java ?
Les paramètres de type n'existent plus à l'exécution : pas de new T(), pas de tableau de T, pas de instanceof avec un type paramétré.
Pourquoi préférer Map<String, Facture> à Map brute ?
Le type brut désactive les contrôles et réintroduit les erreurs de conversion à l'exécution.
Quel est l'intérêt d'un Repository<T> générique ?
Écrire une seule fois les opérations de persistance communes (trouver, enregistrer, supprimer) pour toutes les entités.

Glossaire

Paramètre de type
Variable de type déclarée entre chevrons qui sera remplacée par un type concret.
Borne supérieure
Contrainte qui impose au paramètre d'être un sous-type d'un type donné.
Joker (wildcard)
Notation ? représentant un type inconnu dans un type paramétré.
Invariance
Propriété selon laquelle G<A> et G<B> sont sans lien de sous-typage même si A hérite de B.
Effacement de type
Suppression des informations de type paramétré lors de la compilation Java.
Type brut (raw type)
Utilisation d'une classe générique sans paramètre de type, qui désactive les vérifications.