Sobes.tech
Junior

Quels types de génériques connaissez-vous?

sobes.tech IA

Réponse de l'IA

Invariable, covariante et contravariante.

  • Invariance: Le type List<A> n'est pas un sous-type de List<B> et vice versa, même si A est un sous-type de B. Le type reste exact.
  • Covariance (out): Permet d'utiliser des sous-types. List<A> est un sous-type de List<B> si A est un sous-type de B. Utilisé pour les paramètres de sortie (valeurs retournées).
fun foo(list: List<out Number>) {
    // Peut lire du liste (Number, Double, Int, etc.)
    val number: Number = list[0]
    // Ne peut pas ajouter au liste (on ne sait pas quel type d'éléments attendre)
    // list.add(1) // Erreur de compilation
}
  • Contravariance (in): Permet d'utiliser des super-types. List<B> est un sous-type de List<A> si A est un sous-type de B. Utilisé pour les paramètres d'entrée (arguments).
fun foo(comparable: Comparable<in String>) {
    // Peut passer des arguments String (ou ses super-types)
    val result = comparable.compareTo("hello")
    // Ne peut pas obtenir des résultats de type String (on ne sait pas quel type de résultat)
    // val str: String = comparable.compareTo("world") // Erreur de compilation
}

En Kotlin, ces concepts sont implémentés avec les annotations out et in sur les paramètres de type. En Java, on utilise des wildcards (? extends pour la covariance et ? super pour la contravariance).

Type Objectif Mot-clé (Kotlin) Wildcard (Java) Lecture autorisée Écriture autorisée
Invariant Correspondance exacte de type Non Non Oui Oui
Covariante Utilisation de sous-types (producteur - "out") out ? extends T Oui Non
Contravariante Utilisation de super-types (consommateur - "in") in ? super T Non Oui