— 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:
class WarriorManager
{
public static boolean fight(Warrior w1, Warrior w2)
{
return w1.power > w2.power;
}
}
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.
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 …
}
}
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:
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.
GO TO FULL VERSION