"Szia Amigo! A mai óra témája a típuskonverziók szélesítése és szűkítése. A primitív típusok szélesítéséről és szűkítéséről nagyon régen tanultál. A 10. szinten. Ma arról fogunk beszélni, hogyan működik a referenciatípusoknál, pl. osztályok példányai."

Valójában minden nagyon egyszerű. Képzeljük el egy osztály öröklődési láncát: az osztályt, a szülőjét, a szülő szülőjét stb., egészen az Object osztályig. Mivel egy osztály tartalmazza az általa örökölt osztály összes tagmetódusát , az osztály egy példánya elmenthető egy olyan változóba, amelynek típusa bármely szülőé.

Íme egy példa:

Kód Leírás
class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
Itt van három osztálynyilatkozat: Állat, Macska és Tigris. A macska az állatot örökli. Tigris pedig örökli Cat.
public static void main(String[] args)
{
Tiger tiger = new Tiger();
Cat cat = new Tiger();
Animal animal = new Tiger();
Object obj = new Tiger();
}
Egy Tigris objektum mindig hozzárendelhető egy olyan változóhoz, amelynek típusa az egyik őse típusa. A Tigris osztály esetében ezek a macska, az állat és a tárgy.

Most pedig vessünk egy pillantást a konverziók bővítésére és szűkítésére.

Ha egy hozzárendelési művelet hatására feljebb lépünk az öröklődési láncban (az Object osztály felé), akkor kiszélesedő konverzióról van szó (más néven upcasting). Ha lefelé haladunk a láncon az objektum típusa felé, akkor ez egy szűkítő konverzió (más néven downcasting).

Az öröklődési lánc felfelé haladását szélesítésnek nevezzük, mert ez egy általánosabb típushoz vezet. Ezzel azonban elveszítjük azt a képességet, hogy az osztályhoz adott metódusokat öröklés útján meghívjuk.

Kód Leírás
public static void main(String[] args)
{
Object obj = new Tiger();
Animal animal = (Animal) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) animal;
Tiger tiger2 = (Tiger) cat;
}
A típus szűkítésénél típuskonverziós operátort kell használni, azaz explicit konverziót végzünk.

Ez arra készteti a Java gépet, hogy ellenőrizze, hogy az objektum valóban azt a típust örökli-e, amelyre konvertálni szeretnénk.

Ez a kis újítás többszörösen csökkentette a típusöntési hibák számát, és jelentősen növelte a Java programok stabilitását.

Kód Leírás
public static void main(String[] args)
{
Object obj = new Tiger();
if (obj instanceof Cat)
{
Cat cat = (Cat) obj;
cat.doCatActions();
}}
Még jobb, ha egy ellenőrzési példányt használ 
public static void main(String[] args)
{
Animal animal = new Tiger();
doAllAction(animal);

Animal animal2 = new Cat();
doAllAction(animal2);

Animal animal3 = new Animal();
doAllAction(animal3);
}

public static void doAllAction(Animal animal)
{
if (animal instanceof Tiger)
{
Tiger tiger = (Tiger) animal;
tiger.doTigerActions();
}

if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
cat.doCatActions();
}

animal.doAnimalActions();
}
És itt van miért. Vessen egy pillantást a bal oldali példára.

Mi (a kódunk) nem mindig tudjuk, hogy milyen típusú objektummal dolgozunk. Lehet a változóval azonos típusú objektum (Állat), vagy bármilyen leszármazott típus (Macska, Tigris).

Fontolja meg a doAllAction módszert. Megfelelően működik, függetlenül a bevitt objektum típusától.

Más szóval, mindhárom típusnál megfelelően működik: Állat, Macska és Tigris.

public static void main(String[] args)
{
Cat cat = new Tiger();
Animal animal = cat;
Object obj = cat;
}
Itt három hozzárendelési műveletünk van. Mindegyik példa a szélesebb körű konverziókra.

Itt nincs szükség a típusú cast operátorra, mert nincs szükség ellenőrzésre. Egy objektumhivatkozás mindig tárolható olyan változóban, amelynek típusa az egyik őse.

"Ó, az utolsó előtti példa mindent világossá tett: miért van szükség az ellenőrzésre, és miért van szükség a típusöntésre."

"Remélem. Szeretném felhívni a figyelmét erre a tényre:"

Ezek egyike sem okoz semmilyen változást egy tárgyban! Az egyetlen dolog, ami változik, az egy adott referenciaváltozónál meghívható metódusok száma .

Például egy Cat változó lehetővé teszi a doAnimalActions és a doCatActions metódusok meghívását. Nem tud semmit a doTigerActions metódusról, még akkor sem, ha egy Tiger objektumra mutat.

"Igen, értem. Könnyebb volt, mint gondoltam."