Generické dedenie v Jave: Príklady a využitie

Dedenie je jedným z kľúčových konceptov objektovo orientovaného programovania v Jave. Umožňuje triedam preberať (dediť) vlastnosti a správanie od iných tried, čím sa dosahuje opätovné použitie kódu, modularita a hierarchická organizácia. Generické dedenie, ako špecifická forma dedenia, sa zameriava na prácu s generickými triedami a rozhraniami.

Princípy dedenia v Jave

V objektovo orientovanom programovaní je dedičnosť schopnosť triedy používať vlastnosti a metódy inej triedy a pridávať vlastné funkcie. Triedy, ktoré sú v hierarchii tried na prvých pozíciách, nazývame generické triedy. Označujeme ich aj ako základné alebo rodičovské triedy. Triedy, ktoré vzniknú dedením vlastností z týchto generických tried, sa označujú ako triedy potomkov alebo odvodené triedy. Triede, ktorá je potomkom inej triedy, sa pri definícii pridá pomocou kľúčového slova extends názov triedy, z ktorej dedí.

Základné pojmy dedenia:

  • Generická (rodičovská, základná) trieda: Trieda, od ktorej ostatné triedy dedia.
  • Potomkovská (odvodená) trieda: Trieda, ktorá dedí od inej triedy.
  • extends: Kľúčové slovo, ktoré sa používa na určenie dedičnosti v Jave.

Príklad generického dedenia: Zvieratá

Pre ilustráciu generického dedenia si vytvoríme jednoduchý príklad s triedami reprezentujúcimi zvieratá. Definujme generickú triedu Zviera a odvodené triedy Cicavec, Vtak a Plaz. Následne trieda Pes bude odvodená od triedy Cicavec.

Trieda Zviera bude obsahovať položky spoločné pre všetky druhy zvierat. Triedy Cicavec, Vtak a Plaz budú odvodené od triedy Zviera. Znamená to, že zdedia všetky vlastnosti a metódy triedy Zviera. Znamená to, že každý cicavec, vták a plaz má meno, má určitú hmotnosť, dokáže prijímať potravu a rozmnožovať sa. Uvažujeme s plazmi vo význame hady. Ďalej trieda Pes bude potomkom triedy Cicavec, to znamená že zdedí všetky vlastnosti a metódy z triedy Cicavec, ale aj z triedy Zvera.

Implementácia:

Súbor Zviera.java:

public class Zviera { private String nazov; private double vaha; public Zviera() { this.nazov = "zviera"; this.vaha = 0; } public Zviera(String nazov, double vaha) { this.nazov = nazov; this.vaha = vaha; } public String getNazov() { return nazov; } public void setNazov(String nazov) { this.nazov = nazov; } public double getVaha() { return vaha; } public void setVaha(double vaha) { this.vaha = vaha; }}

Trieda Zviera obsahuje vlastnosti nazov a vaha. Konštruktor Zviera vytvorí novú inštanciu zvieraťa, ktoré bude mať (všeobecný) názov "zviera" a váha bude 0.

Prečítajte si tiež: Ako dediť výsluhový dôchodok?

Súbor Cicavec.java:

public class Cicavec extends Zviera { private int dlzka_gravidity; private String typ_srsti; public Cicavec() { super(); this.dlzka_gravidity = 0; this.typ_srsti = "ziadna"; } public Cicavec(String nazov, double vaha) { super(nazov, vaha); this.dlzka_gravidity = 0; this.typ_srsti = "ziadna"; } public Cicavec(String nazov, double vaha, int dlzka_gravidity, String typ_srsti) { super(nazov, vaha); this.dlzka_gravidity = dlzka_gravidity; this.typ_srsti = typ_srsti; } public int getDlzka_gravidity() { return dlzka_gravidity; } public void setDlzka_gravidity(int dlzka_gravidity) { this.dlzka_gravidity = dlzka_gravidity; } public String getTyp_srsti() { return typ_srsti; } public void setTyp_srsti(String typ_srsti) { this.typ_srsti = typ_srsti; }}

Trieda Cicavec je odvodená od triedy Zviera. Keďže je odvodená z triedy Zviera, zdedí všetky jej verejné vlastnosti a metódy. Pri vytváraní novej inštancie triedy Cicavac (hovoríme o konštruktore triedy Cicavec), je teda potrebné zavolať aj konštruktor nadradenej triedy, teda triedy Zviera. Ten zavoláme pomocou kľúčového slova super. Výraz super() znamená zavolanie konštruktora priamo nadradenej triedy. Ak zavoláme super(), voláme konštruktor Zviera(). Podobne je to aj pri konštruktore Cicavec(nazov, vaha, dlzka_gravidity, typ_srsti), kde voláme metódu super(nazov, vaha). Teda vlastne voláme konštruktor nadradenej triedy: Zviera(nazov, vaha) - teda konštruktor s 2-mi parametrami.

Súbor Plaz.java:

public class Plaz extends Zviera { public Plaz() { super(); } public Plaz(String nazov, double vaha) { super(nazov, vaha); }}

Trieda Plaz je odvodená od triedy Zviera.

Súbor Vtak.java:

public class Vtak extends Zviera { public Vtak() { super(); } public Vtak(String nazov, double vaha) { super(nazov, vaha); }}

Trieda Vtak je odvodená od triedy Zviera.

Súbor Pes.java:

public class Pes extends Cicavec { private String rasa; public Pes() { super(); this.rasa = "neurcena"; } public Pes(String nazov, double vaha, int dlzka_gravidity, String typ_srsti, String rasa) { super(nazov, vaha, dlzka_gravidity, typ_srsti); this.rasa = rasa; } public String getRasa() { return rasa; } public void setRasa(String rasa) { this.rasa = rasa; }}

Trieda Pes je odvodená od triedy Cicavec. Trieda Pes zdedila všetky verejné vlastnosti triedy Cicavec, ale aj triedy Zviera.

Súbor TestZviera.java:

public class TestZviera { public static void main(String[] args) { Zviera zviera = new Zviera("Nejaké zviera", 10.5); Cicavec cicavec = new Cicavec("Macka", 5.2, 60, "husta"); Pes pes = new Pes("Boby", 12.7, 63, "jemna", "Labrador"); System.out.println("Zviera: " + zviera.getNazov() + ", vaha: " + zviera.getVaha()); System.out.println("Cicavec: " + cicavec.getNazov() + ", vaha: " + cicavec.getVaha() + ", dlzka gravidity: " + cicavec.getDlzka_gravidity() + ", typ srsti: " + cicavec.getTyp_srsti()); System.out.println("Pes: " + pes.getNazov() + ", vaha: " + pes.getVaha() + ", dlzka gravidity: " + pes.getDlzka_gravidity() + ", typ srsti: " + pes.getTyp_srsti() + ", rasa: " + pes.getRasa()); }}

V kóde vidieť mechanizmus dedenia.

Prečítajte si tiež: Nároky na dedičstvo po manželovi

Využitie dedenia v praxi

Dedenie je užitočné v mnohých situáciách, vrátane:

  • Opätovné použitie kódu: Dedením sa vyhýbame duplikovaniu kódu a zjednodušujeme údržbu.
  • Rozšíriteľnosť: Pridávaním nových odvodených tried môžeme jednoducho rozširovať funkcionalitu existujúceho kódu.
  • Polymorfizmus: Dedenie umožňuje používať objekty rôznych tried jednotným spôsobom prostredníctvom polymorfizmu.

Java Reflection a dedenie

Java Reflection je mocný nástroj, ktorý umožňuje skúmať a upravovať správanie aplikácií za behu. V kontexte dedenia nám Reflection umožňuje:

  • Získať informácie o nadradenej triede pomocou metódy getSuperclass() triedy Class.
  • Zistiť, ktoré rozhrania trieda implementuje pomocou metódy getInterfaces().
  • Pracovať s metódami a atribútmi zdedenými od nadradenej triedy.

Napríklad, ak chceme zistiť, či trieda dedí z nejakej spoločnej abstraktnej triedy, môžeme použiť getSuperclass() na prechádzanie hierarchiou dedičnosti.

Alternatívy k dedeniu

Hoci dedenie je silný nástroj, nie je vždy najlepším riešením. V niektorých prípadoch môže byť vhodnejšie použiť iné techniky, ako napríklad:

  • Kompozícia: Namiesto dedenia vytvoríme triedu, ktorá obsahuje iné triedy ako svoje atribúty.
  • Rozhrania: Definujeme rozhrania, ktoré triedy implementujú, čím sa dosiahne polymorfizmus bez dedenia.

Príklad: Vlastnosti v C# a dedenie (paralela)

Hoci tento článok je primárne o Jave, je zaujímavé pozrieť sa na podobný koncept v C#, a to na vlastnosti (properties). V C# sa vlastnosti používajú na riadený prístup k členským premenným triedy, podobne ako dedenie umožňuje triedam preberať vlastnosti a správanie.

Prečítajte si tiež: Podmienky dedenia DDS

Definícia public string prispevok { get; set; } v C# predstavuje automatickú vlastnosť typu string. V kontexte webovej aplikácie alebo formulára môže byť vlastnosť prispevok použitá na uloženie a manipuláciu s textom príspevku používateľa.

Podobne ako dedenie, aj vlastnosti umožňujú zapuzdrenie a riadený prístup k dátam.

tags: #generické #dedenie #java #príklad