1. Típusírás
A referenciatípusokat (osztályokat) tároló változók is különböző típusokká alakíthatók. De ez csak egyetlen típushierarchián belül működik. Nézzünk egy egyszerű példát. Tegyük fel, hogy a következő osztályhierarchiával rendelkezünk, amelyben az alábbi osztályok öröklik a fenti osztályokat.
A referenciatípusok, valamint a primitív típusok típusosítása szintén a szélesítő és szűkítő kategóriába sorolható.
Látjuk, hogy a macska osztály örökli a kisállat osztályt, a kisállat osztály pedig az állatok osztályát.
Ha így írunk kódot:
Animal kitten = new Cat();
Ez egy szélesítő típusú átalakítás . Implicit öntvénynek is nevezik. Kiszélesítettük a macska hivatkozást, így most egy Cat objektumra utal . Egy ilyen típusú konverzióval nem tudjuk használni a cica hivatkozást olyan metódusokhoz, amelyek a Cat osztályban jelen vannak, de az Animal osztályban hiányoznak.
A szűkülő konverzió (vagy explicit cast) az ellenkező irányban történik:
Cat cat = (Cat) kitten;
Kifejezetten jeleztük, hogy a cica változóban tárolt referenciát (amelynek típusa az Animal ) a Cat típusra szeretnénk átadni .
2. Egy objektum típusának ellenőrzése
De itt nagyon óvatosnak kell lenni. Ha ezt teszi:
Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;
A fordító engedélyezi ezt a kódot, de a program futása közben hiba lesz ! A JVM kivételt tesz:
Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf
A Cat objektumra való hivatkozások csak olyan változókban tárolhatók, amelyek típusa a Cat osztály egyik őse: Pet, Animal vagy Object.
Miert van az?
Itt az a lényeges, hogy egy objektumhivatkozás az objektum metódusaira és változóira hivatkozik . És akkor sem lesz probléma, ha egy Animal változót használunk a Cat objektumra való hivatkozás tárolására: a Cat típusnak mindig van egy Animal típusú változója és metódusa – örökölte őket!
De ha a JVM lehetővé teszi számunkra, hogy egy Cat objektumra való hivatkozást tároljunk egy Wolf változóban, akkor előfordulhat, hogy megpróbáljuk a grayWolf változót használni egy olyan metódus meghívására, amely nem létezik az abban a változóban tárolt Cat objektumban. . Ezért ez az elrendezés nem megengedett.
A Java speciális instanceof
operátorral rendelkezik, amely lehetővé teszi annak ellenőrzését, hogy egy objektum egy bizonyos típusú-e, és ezért tárolható-e egy bizonyos típusú változóban. Elég egyszerűnek tűnik:
variable instanceof Type
Példa:
Animal beast = new Cat();
if (beast instanceof Wolf)
{
Wolf grayWolf = (Wolf) beast;
}
Ez a kód nem okoz hibát – még futás közben sem.
Íme néhány további példa, amelyek illusztrálják a helyzetet:
Szélesítő típus átalakítás | Leírás |
---|---|
|
Ez egy klasszikus szélesítő konverzió – nincs szükség típuskonverziós operátorra. Most már csak az osztályban definiált metódusok A |
Szűkítő típus átalakítás | |
|
Klasszikus szűkítő konverzió: Hozzá kell adni egy típusellenőrzést és egy cast operátort. A Cow cow változó egy objektumra való hivatkozást tárol Whale . Ellenőrizzük, hogy ez a helyzet , majd végrehajtjuk a (szűkítő) típuskonverziót. Vagy ahogy más néven:
egy típusú öntvény
.
|
|
Szűkíthet egy referenciatípust az objektum típusának ellenőrzése nélkül. Ha a cow változó olyan objektumra hivatkozik, amely nem a Whale , akkor a InvalidClassCastException generálódik. |
3. Az eredeti metódus meghívása: a super
kulcsszó
Amikor felülírjuk egy szülő osztály metódusát, néha ahelyett, hogy a sajátunkkal cserélnénk le, csak kicsit szeretnénk kiegészíteni.
Jó lenne, ha a szülő osztály metódusát be tudnánk használni a metódusunkban, majd végrehajtanánk a saját kódunk egy részét. Vagy talán először futtassuk le a saját kódunkat, majd hívjuk meg a szülő osztály metódusát.
A Java pedig éppen ezt teszi lehetővé. A szülőosztály metódusának meghívásához tegye a következőket:
super.method(arguments);
Példák:
class PeaceTime
{
public double getPi()
{
return 3.14;
}
}
class WarTime extends PeaceTime
{
public double getPi()
{
return super.getPi()*2; // 3.14*2
}
}
Háborús időben a Pi
6 értéke nagyobb lehet! Természetesen viccelünk, de ez a példa bemutatja, hogyan működik mindez.
Íme még néhány példa, hogy kicsit tisztázzuk a dolgokat:
Kód | Leírás |
---|---|
|
Cow és Whale osztályok |
|
A képernyő kimenete a következő lesz:
|
Ez kemény dolog. Őszintén szólva, ez az egyik legnehezebb dolog az OOP -ban . Ennek ellenére tudnia kell és meg kell értenie.