Sprievodca dedením v Jave

1. Prehľad

Jeden zo základných princípov objektovo orientovaného programovania - dedičstvo - umožňuje nám opätovne použiť existujúci kód alebo rozšíriť existujúci typ.

Jednoducho povedané, v Jave môže trieda zdediť inú triedu a viac rozhraní, zatiaľ čo rozhranie môže zdediť ďalšie rozhrania.

V tomto článku začneme s potrebou dedenia a prejdeme k tomu, ako funguje dedenie s triedami a rozhraniami.

Potom sa budeme venovať tomu, ako názvy premenných / metód a modifikátory prístupu ovplyvňujú zdedené členy.

A na konci uvidíme, čo to znamená dediť typ.

2. Potreba dedenia

Predstavte si, že ako výrobca automobilov ponúkate zákazníkom niekoľko modelov automobilov. Aj keď rôzne modely automobilov môžu ponúkať rôzne prvky, ako napríklad strešné okno alebo nepriestrelné okná, všetky obsahujú spoločné komponenty a prvky, ako napríklad motor a kolesá.

Má to zmysel vytvoriť základný dizajn a rozšíriť ho o špecializované verzie, namiesto navrhovania každého modelu automobilu osobitne, od nuly.

Podobným spôsobom, pomocou dedenia, môžeme vytvoriť triedu so základnými vlastnosťami a správaním a vytvoriť jej špecializované verzie vytvorením tried, ktoré dedia túto základnú triedu. Rovnakým spôsobom môžu rozhrania rozširovať existujúce rozhrania.

Všimneme si použitie viacerých výrazov na označenie typu, ktorý je zdedený iným typom, konkrétne:

  • základný typ sa nazýva aj super alebo nadradený typ
  • odvodený typ sa označuje ako rozšírený, podradený alebo podradený typ

3. Dedenie triedy

3.1. Rozšírenie triedy

Trieda môže zdediť inú triedu a definovať ďalších členov.

Začnime definovaním základnej triedy Auto:

verejná trieda Car {int kolesá; Reťazcový model; void start () {// Skontrolujte základné časti}}

Trieda ArmoredCar môže dediť členov Auto trieda od pomocou kľúčového slova predlžuje vo svojom vyhlásení:

public class ArmoredCar rozširuje Car {int bulletProofWindows; void remoteStartCar () {// toto vozidlo je možné naštartovať pomocou diaľkového ovládača}}

Teraz môžeme povedať, že ArmoredCar trieda je podtrieda Auto, a druhá je nadtrieda ArmoredCar.

Triedy v Jave podporujú jednu dedičnosť; the ArmoredCar trieda nemôže rozšíriť viac tried.

Upozorňujeme tiež, že pri absencii súboru predlžuje kľúčové slovo, trieda implicitne dedí triedu java.lang.Objekt.

Trieda podtriedy dedí statické chránené a verejné členovia triedy nadtriedy. Okrem toho členovia s predvolené a balíček prístup sa dedí, ak sú dve triedy v rovnakom balíku.

Na druhej strane súkromné a statický členovia triedy nie sú zdedení.

3.2. Prístup k rodičom z triedy dieťaťa

Na prístup k zdedeným vlastnostiam alebo metódam ich môžeme jednoducho použiť priamo:

public class ArmoredCar rozširuje Car {public String registerModel () {návratový model; }}

Upozorňujeme, že na prístup k jej členom nepotrebujeme odkaz na nadtriedu.

4. Dedičnosť rozhrania

4.1. Implementácia viacerých rozhraní

Aj keď triedy môžu dediť iba jednu triedu, môžu implementovať viac rozhraní.

Predstavte si ArmoredCar ktoré sme definovali v predchádzajúcej časti, je potrebné pre super špióna. Takže Auto výrobná spoločnosť uvažovala o pridaní funkčnosti lietania a plávania:

verejné rozhranie Floatable {void floatOnWater (); }
verejné rozhranie Flyable {void fly (); }
public class ArmoredCar rozširuje Car implementuje Floatable, Flyable {public void floatOnWater () {System.out.println ("I can float!"); } public void fly () {System.out.println ("Môžem lietať!"); }}

V príklade vyššie si všimneme použitie kľúčového slova náradie dediť z rozhrania.

4.2. Problémy s viacnásobným dedením

Java umožňuje viacnásobné dedenie pomocou rozhraní.

Až do Javy 7 to nebol problém. Rozhrania mohli iba definovať abstraktné metódy, teda metódy bez akejkoľvek implementácie. Takže ak trieda implementovala viac rozhraní s rovnakým podpisom metódy, nebol to problém. Implementačná trieda mala nakoniec iba jednu metódu implementácie.

Pozrime sa, ako sa táto jednoduchá rovnica zmenila zavedením predvolené metódy v rozhraniach s Java 8.

Počnúc jazykom Java 8 sa rozhrania mohli rozhodnúť definovať predvolené implementácie svojich metód (rozhranie môže stále definovať abstraktné metódy). To znamená, že ak trieda implementuje viac rozhraní, ktoré definujú metódy s rovnakým podpisom, podradená trieda by dedila samostatné implementácie. Znie to zložito a nie je to povolené.

Java zakazuje dedenie viacerých implementácií rovnakých metód definovaných v samostatných rozhraniach.

Tu je príklad:

verejné rozhranie Floatable {default void repair () {System.out.println ("Oprava objektu Floatable"); }}
verejné rozhranie Flyable {default void repair () {System.out.println ("Oprava Flyable objektu"); }}
public class ArmoredCar rozširuje Car implementuje Floatable, Flyable {// this will not compile}

Ak chceme implementovať obe rozhrania, budeme musieť prepísať príkaz oprava () metóda.

Ak rozhrania v predchádzajúcich príkladoch definujú premenné s rovnakým názvom, povedzme trvanie, nemôžeme k nim získať prístup bez uvedenia názvu premennej s názvom rozhrania:

verejné rozhranie Floatable {int duration = 10; }
verejné rozhranie Flyable {int trvanie = 20; }
public class ArmoredCar extends Car implementuje Floatable, Flyable {public void aMethod () {System.out.println (duration); // nebude kompilovať System.out.println (Floatable.duration); // výstupy 10 System.out.println (Flyable.duration); // výstupy 20}}

4.3. Rozhrania rozširujúce ďalšie rozhrania

Rozhranie môže rozšíriť viac rozhraní. Tu je príklad:

verejné rozhranie Floatable {void floatOnWater (); }
interface interface Flyable {void fly (); }
verejné rozhranie SpaceTraveller rozširuje Floatable, Flyable {void remoteControl (); }

Rozhranie dedí ďalšie rozhrania pomocou kľúčového slova predlžuje. Triedy používajú kľúčové slovo náradie zdediť rozhranie.

5. Typ dedenia

Keď trieda dedí inú triedu alebo rozhrania, dedí okrem svojich členov aj ich typ. To platí aj pre rozhranie, ktoré zdedí ďalšie rozhrania.

Jedná sa o veľmi silný koncept, ktorý vývojárom umožňuje program na rozhranie (základná trieda alebo rozhranie), skôr ako programovanie ich implementácií.

Predstavte si napríklad stav, keď organizácia vedie zoznam automobilov, ktoré vlastnia jej zamestnanci. Všetci zamestnanci môžu samozrejme vlastniť rôzne modely automobilov. Ako teda môžeme označiť rôzne prípady automobilov? Tu je riešenie:

public class Employee {private String name; súkromné ​​auto; // štandardný konštruktor}

Pretože všetky odvodené triedy Auto dediť typ Auto, odvodené inštancie triedy je možné odkazovať pomocou premennej triedy Auto:

Zamestnanec e1 = nový zamestnanec ("Shreya", nový ArmoredCar ()); Zamestnanec e2 = nový zamestnanec („Paul“, nový SpaceCar ()); Zamestnanec e3 = nový zamestnanec („Pavni“, nové BMW ());

6. Členovia skrytej triedy

6.1. Členovia skrytej inštancie

Čo sa stane, ak nadtrieda aj podtrieda definujú premennú alebo metódu s rovnakým názvom? Nebojte sa; stále máme prístup k obom. Musíme však objasniť náš zámer v Jave predponou premennej alebo metódy pred kľúčové slová toto alebo Super.

The toto kľúčové slovo odkazuje na inštanciu, v ktorej sa používa. The Super kľúčové slovo (ako sa zdá zrejmé) odkazuje na inštanciu nadradenej triedy:

public class ArmoredCar rozširuje Car {súkromný model String; public String getAValue () {return super.model; // vráti hodnotu modelu definovaného v základnej triede Car // vrátiť this.model; // vráti hodnotu modelu definovaného v ArmoredCar // vráti model; // vráti hodnotu modelu definovaného v ArmoredCar}}

Mnoho vývojárov používa toto a Super kľúčové slová, aby výslovne uviedli, na ktorú premennú alebo metódu odkazujú. Ich použitie so všetkými členmi však môže spôsobiť, že náš kód bude vyzerať neprehľadne.

6.2. Skrytí statickí členovia

Čo sa stane keď naša základná trieda a podtriedy definujú statické premenné a metódy s rovnakým názvom? Môžeme získať prístup k a statický člena zo základnej triedy, v odvodenej triede, ako to robíme pre premenné inštancie?

Zistíme to na príklade:

public class Car {public static String msg () {return "Car"; }}
public class ArmoredCar rozširuje Car {public static String msg () {return super.msg (); // toto sa nebude kompilovať. }}

Nie, nemôžeme. Statickí členovia patria do triedy a nie do inštancií. Nemôžeme teda použiť nestatické Super kľúčové slovo v správa ().

Pretože statickí členovia patria do triedy, môžeme predchádzajúce volanie upraviť nasledovne:

vrátiť Car.msg ();

Uvažujme o nasledujúcom príklade, v ktorom základná aj odvodená trieda definujú statickú metódu správa () s rovnakým podpisom:

public class Car {public static String msg () {return "Car"; }}
public class ArmoredCar rozširuje Car {public static String msg () {return "ArmoredCar"; }}

Takto ich môžeme nazvať:

Auto ako prvé = nové ArmoredCar (); ArmoredCar second = nový ArmoredCar ();

Pre predchádzajúci kód first.msg () vydá „Auto a second.msg () zobrazí „ArmoredCar“. Statická správa, ktorá sa volá, závisí od typu premennej použitej na odkazovanie ArmoredCar inštancia.

7. Záver

V tomto článku sme sa zaoberali základným aspektom jazyka Java - dedičnosťou.

Videli sme, ako Java podporuje jednoduché dedenie s triedami a viacnásobné dedenie s rozhraniami, a diskutovali sme o komplikovanosti fungovania mechanizmu v jazyku.

Úplný zdrojový kód príkladov je ako vždy k dispozícii na serveri GitHub.


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