Programovanie

Dedenie v Jave, časť 1: Kľúčové slovo extends

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 Friesen

Tento 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 Friesen

Kategó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 Autoa 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: Autoje a špecializovaný Vozidlo a Sporiaci účetje 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ď ÚčetKonš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 AccountDemozdrojový 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 účetpotom Bežný účet. Za predpokladu Account.java, SavingsAccount.java, CheckingAccount.javaa 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é autoje print () metóda má rovnaký názov, návratový typ a zoznam parametrov ako Vozidloje print () metóda. Všimnite si tiež, že Nákladné autoje print () metóda najskôr zavolá Vozidloje 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é autoje print () metóda. Táto metóda najskôr zavolá Vozidloje 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 Vozidloje 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.

$config[zx-auto] not found$config[zx-overlay] not found