"Maintenant, pour un nouveau sujet intéressant : les jokers."

"Essentiellement, c'est quelque chose comme un motif "*" qui correspond à n'importe quoi."

"Mais commençons par le début."

"Imaginez que vous ayez une classe de Guerrier et une méthode qui détermine lequel des deux guerriers est le plus fort. Voici à quoi cela pourrait ressembler :"

Exemple 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Exemple d'appel de méthode
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

boolean isMagicCooler = WarriorManager.fight(mag, archer);

"MagicWarrior et ArcherWarrior héritent tous les deux de Warrior. ."

"C'est un peu simpliste, mais pour un exemple, ça ira."

"D'ACCORD."

"Maintenant, supposons que vous ayez décidé de créer une méthode similaire pour la situation où plusieurs guerriers ont rejoint la mêlée."

Exemple 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }

 public static boolean fight(List<Warrior> w1, List<Warrior> w2)
 {
  return 
 }
}
Exemple d'appel de méthode
ArrayList<MagicWarrior> magi = new ArrayList<MagicWarrior>();
for(int i = 0; i < 10; i++)
 magi.add(new MagicWarrior());

ArrayList<ArcherWarrior> archers = new ArrayList<ArcherWarrior>();
for(int i = 0; i < 10; i++)
 archers.add(new ArcherWarrior());

boolean isMagicCooler = WarriorManager.fight(magi, archers); // Compilation error!

"Mais ici, vous rencontrez une erreur de compilation et vous vous demandez ce qui pourrait ne pas aller."

"Le fait est que MagicWarrior hérite de Warrior , et les objets MagicWarrior peuvent être passés à la méthode fight(Warrior, Warrior)."

"Mais List<MagicWarior> n'hérite pas de List<Warrior> . Donc, vous ne pouvez pas le passer ici !"

« Comment ça, il n'en hérite pas ?

"Je veux dire ceci : l'un est une liste et l'autre est une liste, mais ils ont des paramètres de type."

"Tu as raison. Je ne l'ai pas remarqué tout de suite. Alors, y a-t-il déjà une solution à ce problème ?"

"Oui. Vous devez utiliser une structure plus complexe. Voici à quoi ça ressemble :"

Exemple 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }

 public static boolean fight(List<? extends Warrior> w1, List<? extends Warrior> w2)
 {
  return …
 }
}

"La partie "? étend Guerrier" signifie "tout type qui hérite de Guerrier""

"En d'autres termes, maintenant vous pouvez passer une List<MagicWarrior> et une List<ArcherWarrior>, et tout fonctionnera."

"C'est tellement génial. Moins il y a de tels problèmes, mieux c'est."

"C'est aussi ce que je ressens."

"Mais que se passe-t-il si je n'ai pas besoin de quelque chose qui hérite de Warrior ? Et si je veux pouvoir passer n'importe quelle liste avec n'importe quel paramètre de type à la méthode ? Est-ce autorisé ?"

"Oui, il y a deux formes de notation pour faire ça :"

List<? extends Object>
List<?>

"Ils signifient tous les deux la même chose, donc la deuxième version est généralement utilisée."

"C'est tout pour aujourd'hui."

"Merci, Ellie. J'ai vraiment beaucoup appris aujourd'hui."