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)
DogKeeper
je současně typuPerson
nebo -
např. každý objekt typu (třídy)
Dog
je současně typuPet
-
-
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
-
Podtřída (říká se též potomek, dceřinná třída, subclass) je tedy specializací, zjemněním své nadtřídy (předka),
-
přebírá její vlastnosti,
-
zpravidla přidává další, čímž svou nadtřídu rozšiřuje (
extends
).
Note
|
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 |
Správné použití
-
Dědičnost je správně použita jen tehdy, když opravdu můžeme říci, že každý objekt podtřídy je současně objektem nadtřídy,
-
např.
DogKeeper
je současněPerson
. -
Pokud to realitě neodpovídá, není dědičnost na místě.
Proč se dědičnost používá
-
Abychom zohlednili konceptuální vztah obecnější vs. speciálnější typ.
-
Abychom se pomocí toho vyhnuli opakování kódu a dosáhli znovupoužití.
-
Většinou by mělo platit oboje, aby mělo smysl dědičnost použít.
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
-
Atributy - 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, atributy) nadtřídy,
-
některé zděděné vlastnosti v potomkovi může měnit (metody),
-
případně v potomkovi přidává další vlastnosti (metody, atributy).
Příklad s Account
Cíl: vylepšit třídu Account
(demo 05_Account
)
-
Zdokonalíme náš příklad s účtem tak, aby si účet "hlídal", kolik se z něj převádí peněz, aby zůstatek nebyl nižší než povolený minimální
-
Realizujeme tedy změnu jedné z vlastností — metody
debit
— pomocí jejího překrytí (overriding) -
Zdokonalenou verzi třídy
Account
nazvemeCheckedAccount
Třída Account
public class Account implements Informing { private int balance; ... public boolean debit(int amount) { if(amount <= 0) return false; balance -= amount; return true; } }
Třída CheckedAccount
public class CheckedAccount extends Account { private int minimalBalance; // minimální zůstatek přibývá public CheckedAccount(Person owner, int minimalBalance, int initialBalance) { super(owner, initialBalance); // udělá původní inicializaci Account if(initialBalance < minimalBalance) { // ověří dostatečný poč. zůstatek throw new IllegalArgumentException("initialBalance < minimalBalance"); } this.minimalBalance = minimalBalance; } public boolean debit(int amount) { if(getBalance() - amount >= minimalBalance) { // hlídá si min. zůstatek return super.debit(amount); // je-li zachován, odečte z účtu } else return false; // jinak ne } }
Co tam bylo nového
-
Klíčové slovo
extends
značí, že třídaCheckedAccount
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 metodadebit
třídyCheckedAccount
a program by se zacyklil!