- 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:
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ę:
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:
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:
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:
List<Object> list;
for(MyClass object : list) //ошибка!
{
System.out.println(object.getState());
}
- Jasne. Dzięki za ciekawy wykład.
- Proszę.
GO TO FULL VERSION