Quelle serait l’utilisation de s’accepter comme arguments de type dans les génériques

J’ai vu du code sur une question sans rapport, mais cela m’a rendu curieux, car je n’ai jamais vu une telle construction avec Java Generics. A quoi servirait de créer une classe générique pouvant prendre comme argument de type ou comme descendant de celui-ci. Voici un exemple:

abstract class A<E extends A> { abstract void foo(E x); } 

la première chose qui me vienne à l’esprit serait une liste qui prend une liste comme paramètre. Utiliser ce code est étrange, comment déclarer une variable de type A? Déclaration récursive!?

Est-ce que ça marche même? Si tel est le cas, l’un d’entre vous a-t-il vu cela dans le code? Comment a-t-il été utilisé?


MODIFIER

En fait, il s’est avéré que ma question est la même que celle-ci n’a été formulée que différemment, mais les réponses à cette question répondront également à la mienne.

Merci également pour la référence au modèle de modèle curieusement récurrent qui donne un contexte historique et des explications supplémentaires sur le sujet.

Cette ancienne entrée de blog donne probablement la meilleure explication complète que j’ai trouvée pour nous, les gars de Java.

Il est maintenant difficile de choisir la bonne réponse car toutes les réponses sont utiles, je vais donc choisir celle qui a donné le plus grand nombre de lectures (voir ci-dessus).

Les génériques ne se limitent pas aux conteneurs, comme les listes. Ce type de paramètre de type “S’étend” permet à la superclasse de se référer à la sous-classe à des emplacements tels que les parameters de méthode et les types de retour, même si aucune sous-classe spécifique n’est disponible lors de la compilation de la super-classe. Cela ressemble au modèle de modèle curieusement récurrent en C ++.

Une sous-classe de votre exemple serait déclarée comme

 class Foo extends A 

et la méthode héritée foo() devient

 void foo(Foo x) 

Voyez comment A méthode qui prend un paramètre de Foo définie alors qu’elle ne connaît pas réellement Foo ?

Oui, ce genre de chose est inhabituel, mais pas inouï: la classe Enum intégrée utilise un truc similaire.

Sans cela, le paramètre de la méthode foo ne pourrait pas être lié au type E

Si vous avez une implémentation B de cette classe abstraite, vous pouvez maintenant appliquer cette méthode. foo requirejs également que son paramètre soit de type B

  class B extends A { void foo (B x){} } 

Sans cela, foo devrait prendre n’importe quel type de A

Je conviens que la syntaxe utilisée est moins qu’élégante.