„Acum pentru un subiect nou, interesant: wildcards”.

„În esență, acesta este ceva ca un model «*» care se potrivește cu orice.”

— Dar să începem de la început.

„Imaginați-vă că aveți o clasă Războinici și o metodă care determină care dintre cei doi războinici este mai puternic. Iată cum ar putea arăta:”

Exemplul 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Exemplu de apel de metodă
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

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

„MagicWarrior și ArcherWarrior moștenesc amândoi Warrior. ”.

„Este puțin simplist, dar, de exemplu, va funcționa”.

"BINE."

„Acum să presupunem că ai decis să faci o metodă similară pentru situația în care mai mulți războinici s-au alăturat luptei.”

Exemplul 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 
 }
}
Exemplu de apel de metodă
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!

„Dar aici întâmpinați o eroare de compilare și sunteți nedumerit cu privire la ce ar putea fi greșit.”

„Chestia este că MagicWarrior moștenește Warrior , iar obiectele MagicWarrior pot fi transmise metodei de luptă (Warrior, Warrior).

„Dar List<MagicWarior> nu moștenește List<Warrior> . Deci, nu poți să-l treci acolo!”

„Ce vrei să spui că nu o moștenește?”

„Vreau să spun asta: una este o Listă și cealaltă este o Listă, dar au parametri de tip”.

"Ai dreptate. Cumva nu am observat asta imediat. Deci, există deja o soluție pentru această problemă?"

"Da. Trebuie să folosești o structură mai complexă. Așa arată:"

Exemplul 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 …
 }
}

„Partea „? extinde Războinic” înseamnă „orice tip care moștenește Războinic””

„Cu alte cuvinte, acum poți trece o Listă<MagicWarrior> și o Listă<ArcherWarrior> și totul va funcționa.”

"Este atât de grozav. Cu cât sunt mai puține astfel de probleme, cu atât mai bine."

— Așa mă simt și eu.

"Dar dacă nu am nevoie de ceva care să-l moștenească pe Warrior? Ce se întâmplă dacă vreau să pot transmite metodei orice Listă cu orice parametru de tip? Este permis?"

„Da, există două forme de notație pentru a face asta:”

List<? extends Object>
List<?>

„Amândoi înseamnă același lucru, așa că de obicei se folosește a doua versiune.”

— Asta-i tot pentru azi.

— Mulțumesc, Ellie. Chiar am învățat multe astăzi.