"Szia! Folytatom Ellie leckét a generikus gyógyszerekről. Készen állsz a hallgatásra?"
"Igen."
– Akkor kezdjük.
"Az első dolog, amit tudnod kell, hogy egy osztály metódusainak is lehetnek saját típusparaméterei."
"Tudom."
"Nem, kifejezetten a saját típusparamétereikre gondolok: "
class Calculator
{
T add(T a, T b); // Add
T sub(T a, T b); // Subtract
T mul(T a, T b); // Multiply
T div(T a, T b); // Divide
}
"Ezek a típusparaméterek kifejezetten a metódusokra vonatkoznak. Az osztálynak nincsenek paraméterei. Ezeket a metódusokat akár statikusnak is deklarálhatod, és objektum nélkül hívhatod meg."
"Értem. A típusparaméterek lényege a metódusokban ugyanaz, mint az osztályoknál?"
– Igen. De van valami új.
"Mint már tudja, használhat helyettesítő karaktert a típusdeklarációban. Ezután képzelje el a következő helyzetet:"
public void doSomething(List<? extends MyClass> list)
{
for(MyClass object : list)
{
System.out.println(object.getState()); // Everything works well here.
}
}
"De mi van akkor, ha egy új elemet szeretnénk hozzáadni a gyűjteményhez:"
public void doSomething(List<? extends MyClass> list)
{
list.add(new MyClass()); // Error!
}
"A probléma az, hogy általános esetben a doSomething metódus egy olyan Listát kaphat, amelynek elemei nem MyClass objektumok, hanem a MyClass bármely alosztályának objektumai. De ilyen listához nem lehet MyClass objektumokat hozzáadni!"
"Ah. Szóval mit lehet tenni ez ellen?"
"Semmi. Ebben a helyzetben nem tehetsz semmit. Ez azonban gondolkodásra késztette a Java alkotóit. És kitaláltak egy új kulcsszót: szuper ."
"A szintaxis majdnem ugyanúgy néz ki:"
List<? super MyClass> list
De van egy fontos különbség a kiterjesztett és a szuper között.
"«? kiterjeszti a T-t» azt jelenti, hogy az osztálynak T leszármazottjának kell lennie."
""? szuper T" azt jelenti, hogy az osztálynak T elődjének kell lennie."
"Holy Moly. Akkor ezt hol használják?"
A ""? szuper T» akkor használatos, ha egy metódus T objektumok gyűjteményéhez tartozik. Ebben az esetben ez lehet T objektumok gyűjteménye vagy T bármely őse."
"Ah. Az AT objektum hozzárendelhető egy referenciaváltozóhoz, amelynek típusa T bármelyik őse"
"Őszintén szólva, ezt a megközelítést nem használják túl gyakran. Sőt, van egy hiányossága. Például:"
public void doSomething(List<? super MyClass> list)
{
for(MyClass object : list) // Error!
{
System.out.println(object.getState());
}
}
public void doSomething(List<? super MyClass> list)
{
list.add(new MyClass()); // Everything works well here.
}
– Most az első példa nem működik.
"Mivel a lista akár egy List<Object> is lehet (az Object a MyClass legfelső szuperosztálya), lényegében a következő érvénytelen kódot írjuk:"
List<Object> list;
for(MyClass object : list) // Error!
{
System.out.println(object.getState());
}
– Értem. Köszönöm az érdekes leckét.
"Szívesen."
GO TO FULL VERSION