Dědičnost
-
V realitě často vidíme, že objektové třídy jsou podtřídami, speciálními případy jiných:
-
všechny objekty podtřídy jsou zároveň objekty nadtřídy, např. každý objekt typu (třídy)
ChovatelPsu
je současně typuClovek
nebo -
např. každý objekt typu (třídy)
Pes
je současně typuDomaciZvire
-
-
Někdy to chce realitu trochu zjednodušit, např. zde předpokládat, že v našem výseku reality neexistují psi "nedomácí".
-
Podtřída je tedy "zjemněním" nadtřídy — přebírá její vlastnosti a zpravidla přidává další, rozšiřuje svou nadtřídu/předka.
-
V Javě je každá uživatelem definovaná třída potomkem nějaké jiné — neuvedeme-li předka explicitně, je předkem vestavěná třída
Object
.
Terminologie dědičnosti
-
Nadtřídě (superclass) se také říká "bezprostřední předek", "rodičovská třída"
-
Podtřídě (subclass) se také říká "bezprostřední potomek", "dceřinná třída"
-
Dědění může mít i více "generací", např.
-
Person
←Employee
←Manager
-
Osoba je rodičovskou třídou zaměstnance, ten je rodičovskou třídou manažera.
-
Přeneseně tedy předkem (nikoli bezprostředním) manažera je člověk.
Jak zapisujeme dědění
-
Klíčovým slovem
extends
:public class Employee extends Person { // ... popis vlastností (proměnných, metod...) // zaměstnance navíc oproti (obecnému) člověku... }
Dědičnost a vlastnosti tříd (1)
Opakování:
-
Jak víme, třídy popisují skupiny objektů podobných vlastností.
-
Třídy mohou mít tyto skupiny vlastností :
-
Metody - procedury/funkce, které pracují (především) s objekty této třídy
-
Proměnné - pojmenované datové prvky (hodnoty) uchovávané v každém objektu této třídy
-
-
Vlastnosti jsou ve třídě "schované", tzv. zapouzdřené (encapsulated)
-
Třída připomíná záznam známý např. z Pascalu (
record
) nebo z C jakostruct
. -
Záznamy však zapouzdřují jen proměnné, nikoli metody.
-
Co v tomto přináší dědičnost?
Dědičnost a vlastnosti tříd (2)
Dědičnost (alespoň v javovém smyslu) znamená, že dceřinná třída (podtřída, potomek):
-
má všechny vlastnosti (metody, proměnné) nadtřídy a
-
přidává vlastnosti uvedené přímo v potomkovi
Příklad
-
Cíl: vylepšit třídu
Account
-
Postup:
-
Zdokonalíme náš příklad s účtem tak, aby si účet "hlídal", kolik se z něj převádí peněz
-
Zdokonalenou verzi třídy
Account
nazvemeCreditAccount
-
-
Vzorový zdroják samotný nepůjde přeložit, protože nemáme třídu, na níž závisí.
Příklad — zdrojový kód
public class CreditAccount extends Account { // private double balance; zdědí se z nadtřídy "Account" // zde pamatuji navíc, kolik mohu "jít do mínusu" private double creditLimit; public void add(double amount) { if (balance + creditLimit + amount >= 0) { // přes "super" zavoláme původní "neopatrnou" metodu super.add(amount); } else { System.err.println("Nelze odebrat částku " + (-amount)); } } // writeInfo(), transferTo(Account to, double amount) se zdědí }
Příklad — co tam bylo nového
-
Klíčové slovo
extends
značí, že třídaCreditAccount
je potomkem/podtřídou/rozšířením/dceřinnou třídou (subclass) třídyAccount
. -
Konstrukce
super.metoda(…);
značí, že je volána metoda rodičovské třídy/předka/nadtřídy (superclass). -
Kdyby se to
super
nepoužilo, zavolala by se metodaadd
třídyCreditAccount
a program by se zacyklil!
Další příklad
Demoprojekt (viz IS) private_account
:
-
výchozí třída
Account
-
podědíme do třídy
PrivateAccount
, což je osobní/privátní účet -
zde přibude nová vlastnost (proměnná "vlastník") nesoucí odkaz na osobu vlastnící tento účet.
Příklad na víceúrovňovou dědičnost
-
Neplést s vícenásobnou, ta v Javě není možná.
-
Více úrovněmi myslíme častou situaci, kdy ze třídy odvodíme podtřídu, z ní zase podtřídu…
Demoprojekt (viz IS) checked_private_account
:
-
výchozí třída
Account
(obyčejný účet) -
podědíme do třídy
PrivateAccount
(osobní/privátní účet) -
z ní podědíme do třídy
CheckedPrivateAccount
(osobní účet s kontrolou minimálního zůstatku)