- Cześć! Będę kontynuował wykład Ellie na temat leków generycznych. Gotowy do słuchania?

- Tak.

- Więc zacznijmy.

Fakt pierwszy. Metody klasowe mogą również mieć własne typy-parametry.

- Tak, wiem.

- Nie, mam na myśli dokładnie  moje typy-parametry:

Przykład
class Calculator
{
  T add(T a, T b); //сложить
  T sub(T a, T b); //отнять
  T mul(T a, T b); //умножить
  T div(T a, T b); //делить
}

Są to typy-parametry metody (metod). Klasa nie ma parametrów. Możesz nawet zadeklarować metody jako statyczne i wywoływać je bez użycia obiektu.

- Jasne. Czy znaczenie typów parametrów w metodach jest takie samo jak w klasach?

- Tak. Ale jest też coś nowego.

Jak już wiesz, możesz użyć symbolu wieloznacznego w opisie typu. Następnie wyobraź sobie sytuację:

Przykład 1
public void doSomething(List<? extends MyClass> list)
{
 for(MyClass object : list)
 {
  System.out.println(object.getState()); //тут все работает отлично.
 }
}

A oto co się dzieje, gdy chcemy dodać nowy element do kolekcji:

Przykład 2
public void doSomething(List<? extends MyClass> list)
{
 list.add(new MyClass()); //ошибка!
}

Faktem jest, że w ogólnym przypadku do metody doSomething można przekazać Listę z typem elementu innym niż MyClass, ale dowolnym potomkiem MyClass. I nie ma już możliwości dodawania obiektów MyClass do takiej listy!

- Tak. I co robić?

- Nic. Właśnie w tej sytuacji - nic nie możesz zrobić. Dało to jednak programistom Java coś do myślenia. I wymyślili nowe słowo kluczowe -  super .

Jego użycie wygląda prawie tak samo:

List<? super MyClass> list

Ale istnieje znacząca różnica między rozszerzeniami a super.

"? extends T” oznacza, że ​​klasa musi dziedziczyć po T.

"? super T” oznacza, że ​​klasa musi być przodkiem klasy T.

- Wow. Gdzie jest używany?

- "? super T” jest używane, gdy metoda ma dodać obiekt typu T do kolekcji. Wtedy może to być kolekcja typu T lub dowolny przodek T.

- Tak. Odwołanie do obiektu typu T można również przypisać do dowolnego typu nadrzędnego dla T.

Szczerze mówiąc, to podejście nie jest stosowane zbyt często. Co więcej, ma też wadę. Przykład:

Przykłady
public void doSomething(List<? super MyClass> list)
{
 for(MyClass object : list) //ошибка!
 {
  System.out.println(object.getState());
 }
}
public void doSomething(List<? super MyClass> list)
{
 list.add(new MyClass()); //тут все работает отлично.
}

Teraz pierwszy przykład nie działa.

Ponieważ zbiorem list może być nawet List<Object> (Obiekt jest najwyższym rodzicem MyClass), wtedy faktycznie piszemy taki kod, ale nie można pisać tak:

Przykład 1
List<Object> list; 

for(MyClass object : list) //ошибка!
{ 
 System.out.println(object.getState()); 
}

- Jasne. Dzięki za ciekawy wykład.

- Proszę.