Öröklés
Az előző órákon többször is megemlítette az öröklődést. A Java nyelvben az osztályok más osztályokból származtathatók, ezáltal mezőket és módszereket örökölhetnek ezekből az osztályokból.
Kivéve a
Object
-t, amelynek nincs szuperosztálya, minden osztálynak van egy, és csak egy közvetlen szuperosztály (egyszeri öröklés). Egyéb kifejezett szuperosztály hiányában minden osztály implicit módon a Object
alosztálya. Az osztályok származhatnak olyan osztályokból, amelyek osztályokból származnak, és így tovább, és végül a legfelső osztályból származik,
Object
. Egy ilyen osztály állítólag az öröklési lánc összes osztályából származik, amely Object
-ig nyúlik vissza. Az öröklés ötlete egyszerű, de hatékony: Ha új osztályt szeretnél létrehozni, és máris létezik olyan osztály, amely tartalmazza a kívánt kód egy részét, levezetheted az új osztályt a meglévő osztályról . Ennek során újból felhasználhatja a meglévő osztály mezőit és metódusait anélkül, hogy saját magát kellene megírnia (és hibakeresni!).
Egy alosztály az összes tagot (mezőket, metódusokat és beágyazott osztályokat) örökli szuperosztálya. A konstruktorok nem tagok, ezért nem öröklik őket az alosztályok által, de a szuperosztály konstruktora meghívható az alosztályból.
A Java Platform osztály hierarchiája
A iv id = A java.lang
csomagban definiált “e946c849b8”> osztály meghatározza és megvalósítja az összes osztály – köztük az Ön által írt – viselkedését. A Java platformon sok osztály közvetlenül származik a Object
-ből, más osztályok ezekből az osztályokból származnak, és így tovább, az osztályok hierarchiáját alkotva.
A Java platform összes osztálya az objektum leszármazottja
A hierarchia tetején az Object
az összes osztály közül a legáltalánosabb. A hierarchia alján található osztályok speciálisabb viselkedést biztosítanak.
Példa az öröklődésre
Itt található a mintakód egy Bicycle
osztály:
Osztály deklaráció egy MountainBike
osztályhoz, amely az így nézhet ki:
public class MountainBike extends Bicycle { // the MountainBike subclass adds one field public int seatHeight; // the MountainBike subclass has one constructor public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } // the MountainBike subclass adds one method public void setHeight(int newValue) { seatHeight = newValue; } }
MountainBike
örökli az Bicycle
összes mezőjét és metódusát, és hozzáadja a seatHeight
mezőt és egy módszert annak beállításához. A konstruktort leszámítva olyan, mintha teljesen újból írtál volna egy új osztályt MountainBike
, négy mezővel és öt módszerrel. Azonban nem kellett elvégeznie az összes munkát. Ez különösen értékes lenne, ha a Bicycle
osztály metódusai összetettek lennének, és jelentős időt igényelnének a hibakereséshez.
Mit tehet egy alosztályban
Az alosztály örökli a szülő összes nyilvános és védett tagját, függetlenül attól, hogy az alosztály melyik csomagban van. Ha az alosztály ugyanabban a csomagban van, mint az alosztály szülő, a szülő csomag-privát tagjait is örökli. Használhatja az örökölt tagokat olyan állapotban, kicserélheti őket, elrejtheti őket, vagy új tagokkal egészítheti ki őket:
- Az örökölt mezők közvetlenül használható, csakúgy, mint bármely más mezőt.
- Az alosztályban egy olyan mezőt deklarálhat, amelynek neve ugyanaz, mint a szuperosztályban, így elrejti azt (nem ajánlott).
- Az alosztályban olyan új mezőket deklarálhat, amelyek nincsenek a szuperosztályban.
- Az örökölt módszerek közvetlenül felhasználhatók olyanok, amilyenek.
- Új példány-metódust írhat a alosztálya ugyanolyan aláírással rendelkezik, mint a szuperosztályban, így felülírja azt.
- Az alosztályba írhat egy új statikus metódust, amely ugyanazzal az aláírással rendelkezik, mint a szuperosztályban, így elrejti azt.
- Az alosztályban olyan új módszereket deklarálhat, amelyek nincsenek a szuperosztályban.
- Írhat olyan alosztály konstruktort, amely implicit módon vagy a
super
.
A lecke következő szakaszai kibővítik ezeket a témákat.
Magán tagok egy szuperosztályon
Egy alosztály nem örökli a szülőosztály private
tagjait. Ha azonban a szuperosztály nyilvános vagy védett módszerekkel rendelkezik a privát területeihez való hozzáféréshez, ezeket az alosztály is felhasználhatja.
A beágyazott osztály hozzáfér a csatoló osztály összes privát tagjához – a mezőkhöz és a metódusokhoz egyaránt. Ezért egy alosztály által örökölt nyilvános vagy védett beágyazott osztály közvetett hozzáféréssel rendelkezik a szuperosztály összes privát tagjához.
Objektumok leadása
Láttuk, hogy egy objektum a annak az osztálynak az adattípusa, ahonnan példányosították. Például, ha a következőt írjuk:
public MountainBike myBike = new MountainBike();
, akkor a myBike
MountainBike
.
MountainBike
a Bicycle
és a Object
. Ezért egy MountainBike
egy Bicycle
és egyben Object
is, és lehet mindenhol használatos, ahol Bicycle
vagy Object
objektumokat hívnak meg.
A fordított nem feltétlenül igaz: a Bicycle
lehet MountainBike
, de nem feltétlenül. Hasonlóképpen, egy Object
lehet Bicycle
vagy egy MountainBike
, de ez nem feltétlenül szükséges.
Az öntés egy objektum használatát mutatja típus egy másik típus helyett, az öröklés és a megvalósítás által engedélyezett objektumok között. Például, ha a következőt írjuk:
Object obj = new MountainBike();
, akkor obj
mindkettő Object
és egy MountainBike
(amíg obj
másik objektumot kap, amely nem egy MountainBike
). Ezt hívjuk implicit castingnak.
Ha viszont a következőt írjuk:
MountainBike myBike = obj;
kapjon fordítási idejű hibát, mert a obj
nem ismert a fordító számára MountainBike
. Azt azonban elmondhatjuk a fordítónak, hogy ígérjük, hogy egy MountainBike
-t kijelölünk obj
-hez explicit casting segítségével:
MountainBike myBike = (MountainBike)obj;
Ez az öntött szerepkör futtat egy futásidejű ellenőrzést, hogy obj
MountainBike
, hogy a fordító nyugodtan feltételezhesse, hogy obj
egy MountainBike
. Ha a obj
futás közben nem egy MountainBike
, akkor kivételt dobunk.
instanceof
operátor segítségével. Ez megmenthet egy futásidejű hibától a nem megfelelő leadás miatt. Például:
if (obj instanceof MountainBike) { MountainBike myBike = (MountainBike)obj;}
Itt az instanceof
operátor ellenőrzi, hogy obj
egy MountainBike
-re utal, hogy a stábot tudatossá tegyük azzal, hogy nem lesz dobott futásidejű kivétel.