— Нова цікава тема — wildcards.
За змістом це щось на зразок шаблону «*», який збігається з чим завгодно.
Але давай почнемо здалеку.
Уяви, що в тебе є клас «Warrior(Воїн)» і метод, що обчислює, який із двох воїнів сильніший. Ось як, наприклад, це могло б виглядати:
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 та ArcherWarrior – це класи-спадкоємці від Warrior.
Трохи простувато, але для прикладу підійде.
— Ок.
— І ось припустимо, що ти вирішив зробити аналогічний метод, де вже б'ються воїни, стінка на стіну.
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); //помилка компіляції!
І ось тут ти зустрічаєш помилку компіляції і замислюєшся: а що не так?
Справа в тому, що MagicWarrior – це спадкоємець Warrior, і його об'єкти можна передавати до методу fight(Warrior, Warrior)
А ось List<MagicWarrior> — це не спадкоємець List<Warrior>. І передавати його туди не можна!
— Як це не спадкоємець?
— А ось так. Те List і те – List. Нехай і з параметрами.
— Так, а я якось одразу не звернув на це уваги. І що, вже є вирішення цієї проблеми?
— Ага. Для цього використовується складніша конструкція. Виглядає це так:
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» позначає «будь-який тип, що успадковано від Warrior».
Тобто туди можна передати список List<MagicWarrior> та список List<ArcherWarrior>, і все буде працювати.
— Так це ж чудово. Чим менше проблем такого типу, тим краще.
— Так і я ж про це.
— А якщо мені не потрібен спадкоємець Warrior? Що якщо я хочу, щоб до методу можна було передати будь-який List із будь-яким параметром? Так можна?
— Так, для опису цієї ситуації існує два записи:
List<? extends Object>
List<?>
Вони еквівалентні за змістом, тому зазвичай використовують другу.
У мене – все.
— Дякую, Дієго, дійсно дізнався сьогодні багато нового.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ