Java podporuje opätovné použitie tried prostredníctvom dedenia a zloženia. Tento dvojdielny tutoriál vás naučí, ako používať dedičstvo vo vašich programoch Java. V 1. časti sa dozviete, ako používať predlžuje
kľúčové slovo na odvodenie podradenej triedy z nadradenej triedy, vyvolanie konštruktorov a metód nadradenej triedy a prepísanie metód. V časti 2 absolvujete prehliadku java.lang.Objekt
, čo je nadtrieda Java, z ktorej dedí každá iná trieda.
Ak chcete dokončiť svoje učenie o dedičnosti, nezabudnite si prečítať môj tip v jazyku Java s vysvetlením, kedy použiť zloženie vs dedičnosť. Dozviete sa, prečo je kompozícia dôležitým doplnkom dedičstva a ako ju používať na ochranu pred problémami so zapuzdrením vo vašich programoch Java.
stiahnuť Získajte kód Stiahnite si zdrojový kód napríklad pre aplikácie v tejto príručke. Vytvoril Jeff Friesen pre JavaWorld.Dedičnosť v jazyku Java: Dva príklady
Dedenie je programovací konštrukt, ktorý vývojári softvéru používajú na vytvorenie je-vzťah medzi kategóriami. Dedenie nám umožňuje odvodiť konkrétnejšie kategórie od všeobecnejších. Konkrétnejšia kategória je a druh generickejšej kategórie. Napríklad bežný účet je druh účtu, na ktorom môžete uskutočňovať vklady a výbery. Podobne je nákladné vozidlo druhom vozidla, ktoré sa používa na ťahanie veľkých predmetov.
Dedičstvo môže prechádzať cez niekoľko úrovní, čo vedie k stále konkrétnejším kategóriám. Ako príklad zobrazuje obrázok 1 auto a nákladné auto zdedené z vozidla; kombi dediace z automobilu; a smetiarske auto dediace z nákladného auta. Šípky smerujú od konkrétnejších „detských“ kategórií (nižšie dole) k menej konkrétnym „rodičovským“ kategóriám (vyššie hore).
Jeff FriesenTento príklad ilustruje slobodné dedičstvo v ktorej podradená kategória dedí stav a správanie z jednej bezprostrednej nadradenej kategórie. Naproti tomu viacnásobné dedičstvo umožňuje detskej kategórii dediť stav a správanie z dvoch alebo viacerých bezprostredných nadradených kategórií. Hierarchia na obrázku 2 ilustruje viacnásobné dedičstvo.
Jeff FriesenKategórie sú popísané v triedach. Java podporuje jednotlivé dedičstvá prostredníctvom rozšírenie triedy, v ktorej jedna trieda priamo dedí prístupné polia a metódy z inej triedy jej rozšírením. Java však nepodporuje viacnásobné dedenie prostredníctvom rozšírenia triedy.
Pri prezeraní hierarchie dedičstva môžete ľahko zistiť viacnásobné dedičstvo podľa prítomnosti kosoštvorcového vzoru. Obrázok 2 zobrazuje tento vzorec v kontexte vozidla, pozemného vozidla, vodného vozidla a vznášadla.
Kľúčové slovo extends
Java podporuje rozšírenie triedy cez internet predlžuje
kľúčové slovo. Ak sú prítomné, predlžuje
špecifikuje vzťah rodič - dieťa medzi dvoma triedami. Nižšie používam predlžuje
nadviazať vzťah medzi triedami Vozidlo
a Auto
a potom medzi Účet
a Sporiaci účet
:
Zoznam 1. The predlžuje
kľúčové slovo určuje vzťah rodič - dieťa
trieda Vozidlo {// deklarácie členov} trieda Auto rozširuje Vozidlo {// dedí prístupné členy z Vozidla // poskytuje vlastné deklarácie členov} trieda Účet {// deklarácie členov} trieda SavingsAccount rozširuje Účet {// dedí prístupné členov z Účtu // poskytovať vlastné členské vyhlásenia}
The predlžuje
kľúčové slovo je zadané za názvom triedy a pred názvom inej triedy. Názov triedy predtým predlžuje
identifikuje dieťa a názov triedy za predlžuje
identifikuje rodiča. Nie je možné určiť viac názvov tried predlžuje
pretože Java nepodporuje viacnásobné dedenie založené na triedach.
Nasledujúce príklady kodifikujú vzťahy typu is-a: Auto
je a špecializovaný Vozidlo
a Sporiaci účet
je a špecializovaný Účet
. Vozidlo
a Účet
sú známe ako základné triedy, materské triedyalebo nadtriedy. Auto
a Sporiaci účet
sú známe ako odvodené triedy, triedy pre detialebo podtriedy.
Záverečné triedy
Môžete deklarovať triedu, ktorá by sa nemala rozširovať; napríklad z bezpečnostných dôvodov. V Jave používame konečné
kľúčové slovo, aby sa zabránilo rozšíreniu niektorých tried. Jednoducho vložte predponu záhlavia triedy pomocou konečné
, ako v záverečná trieda Heslo
. Na základe tohto vyhlásenia kompilátor nahlási chybu, ak sa niekto pokúsi rozšíriť Heslo
.
Podradené triedy dedia prístupné polia a metódy od svojich rodičovských tried a iných predkov. Nikdy však nezdedia konštruktérov. Namiesto toho podradené triedy deklarujú svojich vlastných konštruktérov. Ďalej môžu deklarovať svoje vlastné oblasti a metódy, pomocou ktorých sa odlíšia od rodičov. Zvážte zoznam 2.
Zoznam 2. An Účet
rodičovská trieda
trieda Účet {súkromný názov reťazca; súkromná dlhá suma; Účet (názov reťazca, dlhá suma) {this.name = name; setAmount (suma); } neplatný vklad (dlhá suma) {this.amount + = suma; } Reťazec getName () {návratové meno; } long getAmount () {vratna suma; } void setAmount (dlhé množstvo) {this.amount = suma; }}
Výpis 2 popisuje všeobecnú triedu bankového účtu, ktorá má názov a počiatočnú sumu a ktoré sú obidve nastavené v konštruktore. Používateľom tiež umožňuje uskutočňovať vklady. (Výbery môžete robiť vkladom záporných súm peňazí, ale túto možnosť budeme ignorovať.) Upozorňujeme, že pri vytváraní účtu musí byť nastavený názov účtu.
Reprezentujúce hodnoty mien
počet drobných. Môžete radšej použiť a dvojitý
alebo a plavák
ukladať peňažné hodnoty, ale to môže viesť k nepresnostiam. Pre lepšie riešenie zvážte BigDecimal
, ktorá je súčasťou štandardnej knižnice tried Java.
Zoznam 3 predstavuje a Sporiaci účet
detská trieda, ktorá rozširuje svoju Účet
rodičovská trieda.
Výpis 3. A Sporiaci účet
detská trieda rozširuje svoje Účet
rodičovská trieda
trieda SavingsAccount rozširuje Účet {SavingsAccount (dlhá suma) {super ("úspora", suma); }}
The Sporiaci účet
trieda je triviálna, pretože nepotrebuje deklarovať ďalšie polia alebo metódy. Deklaruje však konštruktor, ktorý inicializuje polia v jeho Účet
nadtrieda. Inicializácia sa stane, keď Účet
Konštruktor sa volá cez Java Super
kľúčové slovo, za ktorým nasleduje zoznam argumentov v zátvorkách.
Kedy a kde volať super ()
Len ako toto ()
musí byť prvým prvkom v konštruktore, ktorý volá iného konštruktora v rovnakej triede, Super()
musí byť prvým prvkom v konštruktore, ktorý volá konštruktor vo svojej nadtriede. Ak toto pravidlo porušíte, kompilátor nahlási chybu. Kompilátor tiež nahlási chybu, ak zistí a Super()
vyvolať metódu; iba niekedy zavolaj Super()
v konštruktore.
Výpis 4 sa ďalej rozširuje Účet
s Bežný účet
trieda.
Výpis 4. A Bežný účet
detská trieda rozširuje svoje Účet
rodičovská trieda
trieda CheckingAccount rozširuje Účet {CheckingAccount (dlhá suma) {super ("kontrola", suma); } zrušiť výber (dlhá suma) {setAmount (getAmount () - suma); }}
Bežný účet
je o niečo podstatnejšia ako Sporiaci účet
pretože vyhlasuje a vybrať ()
metóda. Všimnite si volania tejto metódy na setAmount ()
a getAmount ()
, ktoré Bežný účet
dedí z Účet
. Nemáte priamy prístup k čiastka
pole v Účet
pretože toto pole je deklarované súkromné
(pozri zoznam 2).
super () a konštruktor bez argumentov
Ak Super()
nie je zadaný v konštruktore podtriedy, a ak nadtrieda nedeklaruje a bez argumentu
konštruktor, potom kompilátor nahlási chybu. Je to tak preto, lebo konštruktor podtriedy musí volať a bez argumentu
konštruktor nadtriedy, keď Super()
nie je prítomný.
Príklad hierarchie tried
Vytvoril som AccountDemo
trieda aplikácií, ktorá vám umožní vyskúšať Účet
triedna hierarchia. Najskôr sa pozrite na AccountDemo
zdrojový kód.
Zoznam 5. AccountDemo
demonštruje hierarchiu tried účtov
trieda AccountDemo {public static void main (String [] args) {SavingsAccount sa = nový SavingsAccount (10 000); System.out.println ("názov účtu:" + sa.getName ()); System.out.println ("počiatočná suma:" + sa.getAmount ()); sa.deposit (5000); System.out.println ("nová suma po vklade:" + sa.getAmount ()); CheckingAccount ca = nový CheckingAccount (20 000); System.out.println ("názov účtu:" + ca.getName ()); System.out.println ("počiatočná suma:" + ca.getAmount ()); ca. vklad (6000); System.out.println ("nová suma po vklade:" + ca.getAmount ()); cca. výber (3000); System.out.println ("nová suma po výbere:" + ca.getAmount ()); }}
The hlavný()
metóda v zozname 5 najskôr demonštruje Sporiaci účet
potom Bežný účet
. Za predpokladu Account.java
, SavingsAccount.java
, CheckingAccount.java
a AccountDemo.java
zdrojové súbory sú v rovnakom adresári, vykonaním niektorého z nasledujúcich príkazov vykonajte kompiláciu všetkých týchto zdrojových súborov:
javac AccountDemo.java javac * .java
Aplikáciu spustíte vykonaním nasledujúceho príkazu:
java AccountDemo
Mali by ste dodržiavať nasledujúci výstup:
názov účtu: počiatočná suma sporenia: 10 000 nová suma po vklade: 15 000 názov účtu: kontrola pôvodnej sumy: 20 000 nová suma po vklade: 26 000 nová suma po výbere: 23 000
Prepísanie metódy (a preťaženie metódy)
Podtrieda môže prepísať (nahraďte) zdedenú metódu, aby sa namiesto toho volala verzia metódy podtriedy. Prepísaná metóda musí zadávať rovnaký názov, zoznam parametrov a návratový typ ako prepísaná metóda. Na demonštráciu som vyhlásil a print ()
metóda v Vozidlo
triedy nižšie.
Zoznam 6. Vyhlásenie a print ()
spôsob, ktorý má byť prepísaný
trieda Vehicle {private String make; súkromný reťazcový model; súkromný int rok; Vozidlo (značka, model reťazca, int rok) {this.make = značka; this.model = model; this.year = year; } String getMake () {return make; } String getModel () {návratový model; } int getYear () {rok návratu; } void print () {System.out.println ("Make:" + make + ", model:" + model + ", rok:" + rok); }}
Ďalej prepíšem print ()
v Nákladné auto
trieda.
Výpis 7. Prepísanie print ()
v Nákladné auto
podtrieda
nákladné vozidlo triedy rozširuje vozidlo {dvojitá súkromná tonáž; Nákladné auto (značka, model reťazca, rok výroby, dvojitá tonáž) {super (značka, model, rok); this.tonnage = tonáž; } dvojnásobok getTonnage () {návratnosť; } void print () {super.print (); System.out.println ("Tonáž:" + tonáž); }}
Nákladné auto
je print ()
metóda má rovnaký názov, návratový typ a zoznam parametrov ako Vozidlo
je print ()
metóda. Všimnite si tiež, že Nákladné auto
je print ()
metóda najskôr zavolá Vozidlo
je print ()
metóda predponou Super.
na názov metódy. Často je dobré najskôr vykonať logiku nadtriedy a až potom vykonať logiku podtriedy.
Volanie metód nadtriedy z metód podtried
Ak chcete zavolať metódu nadtriedy z metódy prevládajúcej podtriedy, vložte pred názov metódy vyhradené slovo Super
a operátor prístupu členov. V opačnom prípade nakoniec rekurzívne zavoláte prevládajúcu metódu podtriedy. V niektorých prípadoch bude podtrieda maskovaťsúkromné
polia nadtriedy vyhlásením polí s rovnakým názvom. Môžeš použiť Super
a operátor prístupu členov na prístup ksúkromné
polia nadtriedy.
Na dokončenie tohto príkladu som vyňal a VehicleDemo
triedy hlavný()
metóda:
Nákladné vozidlo = nový nákladný automobil („Ford“, „F150“, 2008, 0,5); System.out.println ("Make =" + truck.getMake ()); System.out.println ("Model =" + truck.getModel ()); System.out.println ("Rok =" + truck.getYear ()); System.out.println ("Tonnage =" + truck.getTonnage ()); truck.print ();
Posledný riadok, truck.print ();
, volá nákladné auto
je print ()
metóda. Táto metóda najskôr zavolá Vozidlo
je print ()
na výstup značka, model a rok nákladného vozidla; potom vydá tonáž nákladného vozidla. Táto časť výstupu je uvedená nižšie:
Značka: Ford, Model: F150, rok: 2008 Tonáž: 0,5
Na blokovanie prepísania metódy použite final
Príležitostne možno budete musieť vyhlásiť metódu, ktorá by nemala byť prepísaná, z bezpečnostných dôvodov alebo z iného dôvodu. Môžete použiť konečné
kľúčové slovo na tento účel. Aby ste zabránili prepísaniu, jednoducho vložte pred hlavičku metódy predponu konečné
, ako v posledný reťazec getMake ()
. Kompilátor potom nahlási chybu, ak sa niekto pokúsi prepísať túto metódu v podtriede.
Preťaženie metódy a prepísanie
Predpokladajme, že ste vymenili print ()
metóda uvedená v zozname 7 s nasledujúcou:
void print (vlastník reťazca) {System.out.print ("Vlastník:" + vlastník); super.tlač (); }
Upravené Nákladné auto
trieda má teraz dve print ()
metódy: predchádzajúca explicitne deklarovaná metóda a metóda zdedená z Vozidlo
. The neplatná tlač (vlastník reťazca)
metóda neprepíše Vozidlo
je print ()
metóda. Namiesto toho preťaženia to.
Môžete zistiť pokus o preťaženie namiesto prepísania metódy v čase kompilácie predponou hlavičky metódy podtriedy pomocou @ Override
anotácia:
@Override void print (vlastník reťazca) {System.out.print ("Vlastník:" + vlastník); super.tlač (); }
Konkretizujem @ Override
oznámi kompilátoru, že daná metóda má prednosť pred inou metódou. Ak by sa niekto pokúsil namiesto toho preťažiť metódu, kompilátor by nahlásil chybu. Bez tejto anotácie by kompilátor nehlásil chybu, pretože preťaženie metódy je legálne.
Kedy použiť @Override
Rozvíjajte si zvyk predponovať prednostné metódy pomocou @ Override
. Tento zvyk vám pomôže odhaliť chyby preťaženia oveľa skôr.