— Nowy interesujący temat — symbole wieloznaczne.

Z definicji jest to coś w rodzaju wzorca „*”, który pasuje do wszystkiego.

Ale zacznijmy od daleka.

Wyobraź sobie, że masz klasę „Wojownik(Wojownik)” i metodę, która oblicza, który z dwóch wojowników jest silniejszy. Oto jak może to wyglądać na przykład:

Przykład 1
class WarriorManager
{
 public static boolean fight(Warrior w1, Warrior w2)
 {
  return w1.power > w2.power;
 }
}
Przykład połączenia
MagicWarrior mag = new MagicWarrior();
ArcherWarrior archer = new ArcherWarrior();

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

MagicWarrior i  ArcherWarrior  to klasy pochodne od  Warrior .

Trochę proste, ale na przykład wystarczy.

- OK.

- I powiedzmy, że zdecydujesz się na podobną metodę, w której wojownicy już walczą od ściany do ściany.

Przykład 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 
 }
}
Przykład połączenia
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); //ошибка компиляции!

I tutaj napotykasz błąd kompilacji i zastanawiasz się, co jest nie tak?

Rzecz w tym, że  MagicWarrior jest następcą Warriora  i jego obiekty można przekazać do metody fight(Warrior, Warrior)

Ale  List<MagicWarrior> nie jest potomkiem List<Warrior> . I nie możesz go tam wysłać!

Jak to nie jest spadkobiercą?

- I tak. Ta Lista i ta - Lista. Niech i z parametrami.

Tak, ale na początku nie zwróciłem na to uwagi. A czy jest już rozwiązanie tego problemu?

- Tak. W tym celu stosuje się bardziej złożony projekt. To wygląda tak:

Przykład 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}
}

"? extends Warrior” oznacza „dowolny typ, który dziedziczy po Warrior”.

Te. możesz tam przekazać List<MagicWarrior> i List<ArcherWarrior> i wszystko będzie działać.

- Więc to świetnie. Im mniej takich problemów, tym lepiej.

- Więc mówię o tym samym.

„A co, jeśli nie potrzebuję następcy wojownika?” Co zrobić, jeśli chcę mieć możliwość przekazania dowolnej listy z dowolnym parametrem do metody? Więc to możliwe?

— Tak, istnieją dwa wpisy opisujące tę sytuację:

List<? extends Object>
List<?>

Są one równoważne w znaczeniu, więc zwykle używa się drugiego.

To wszystko, co chciałem powiedzieć.

— Dziękuję, Ellie, naprawdę wiele się dzisiaj nauczyłam.