24. listopadu 2013, Brno Připravil: David Procházka Dědičnost Základy objektového návrhu
Časná a pozdní vazba Strana 2 / 22 Obsah přednášky 1 Časná a pozdní vazba 2 Rozhraní pro dědičnost 3 Konstruktory a destruktory 4 Shrnutí
Časná a pozdní vazba Strana 3 / 22 Připomenutí 1 int main (){ 2 Otec * tata = new Otec ; 3 tata -> predstavse (); 4 Syn * synek = new Syn ; 5 synek -> predstavse (); 6 Otec * pokus = new Syn ; 7 pokus -> predstavse (); 8... 9 } Při posledním zavolání se vypíše Jsem otec přestože se fyzicky pracuje s instancí třídy Syn. Důvodem je vyhodnocení volání v době překladu časná vazba.
Časná a pozdní vazba Strana 4 / 22 Pozdní vazba Pozdní vazba K tomu, abychom volali metodu podle instance třídy, na kterou ukazatel ukazuje, musíme překladači říct, aby volání metody vyhodnotil až za běhu programu. Tomuto vyhodnocení říkáme pozdní vazba. U časné vazby se ignoruje druh dosazené instance. Pokud by předek neměl metodu implementovánu, nastala by dokonce chyba. V C++ řešíme pomocí klíčového slova virtual u deklarace metody.
Časná a pozdní vazba Strana 5 / 22 Pozdní vazba: příklad 1 class Otec { 2 public : 3 virtual void predstavse (){ 4 cout << " Jsem otec " << endl ; 5 } 6 }; 7 8 class Syn : public Otec { 9 public : 10 void predstavse (){ 11 cout << " Jsem syn " << endl ; 12 } 13 };
Rozhraní pro dědičnost Strana 6 / 22 Obsah přednášky 1 Časná a pozdní vazba 2 Rozhraní pro dědičnost 3 Konstruktory a destruktory 4 Shrnutí
Rozhraní pro dědičnost Strana 7 / 22 Čistě virtuální metoda Čistě virtuální metoda Virtuální metoda, která má pouze definované rozhraní, ale nemá implementaci, je označována za čistě virtuální metodu. Taková metoda slouží k tomu, aby vynutila svoji existenci v potomcích. Např.: čistě virtuální metoda vykresli, v C++ zapsaná: void vykresli() = 0;
Rozhraní pro dědičnost Strana 8 / 22 Abstraktní třída Abstraktní třída Třída, která obsahuje alespoň jednu čistě virtuální metodu je abstraktní třída. Umožňuje definovat rozhraní, které musí splňovat všichni potomci. Abstraktní třídy slouží pouze k dědění, nemohou mít vlastní instance. V řadě jazyků je pro vynucení rozhraní použit místo abstraktní třídy tzv. interface.
Rozhraní pro dědičnost Strana 9 / 22 Abstraktní třída Abstraktní třída Třída, která obsahuje alespoň jednu čistě virtuální metodu je abstraktní třída. Umožňuje definovat rozhraní, které musí splňovat všichni potomci. Abstraktní třídy slouží pouze k dědění, nemohou mít vlastní instance. V řadě jazyků je pro vynucení rozhraní použit místo abstraktní třídy tzv. interface.
Rozhraní pro dědičnost Strana 10 / 22 Příklad: Grafické objekty Visual Paradigm for UML Standard Edition(Faculty of Business and Economics, Mendel University of Agriculture and Forestry in Brno) GrafickyObjekt #stredx : int #stredy : int +GrafickyObjekt(stredX : int, stredy : int) +vykresli() : void +getobsah() : int +getobvod() : int Kruh -polomer : int +Kruh(stedX : int, stredy : int, polomer : int) +vykresli() : void +getobvod() : int +getobsah() : int Ctverec -velikoststrany : int +Ctverec(stredX : int, stredy : int, strana : int) +vykresli() : void +getobvod() : int +getobsah() : int
Konstruktory a destruktory Strana 11 / 22 Obsah přednášky 1 Časná a pozdní vazba 2 Rozhraní pro dědičnost 3 Konstruktory a destruktory 4 Shrnutí
Konstruktory a destruktory Strana 12 / 22 Virtuální konstruktor/destruktor Nemá smysl aby konstruktor byl virtuální. 1 Destruktor může být virtuální. Virtuální destruktor Umožní zavolat destruktor potomka místo pouze obecného destruktoru předka. Pokud je např. u potomka kompozice. Je u předka virtuální destruktor nezbytností. 1 Když vytvářím instanci vím, jaké je třídy (new A).
Konstruktory a destruktory Strana 13 / 22 Dědičnost a konstruktory Postupně se vždy volají konstruktory předků, až po konstruktor aktuální třídy. Pokud nestanovíme jinak, volají se bezparametrické konstruktory předků nebo implicitní konstruktory. Pokud předek nemá bezparametrický konstruktor (nebo není zcela bez konstruktorů), musí se explicitně vybrat, který parametrický konstruktor se má volat a jakými parametry.
Konstruktory a destruktory Strana 14 / 22 Dědičnost a konstruktory: příklad 1 class GrafickyObjekt { 2 protected : 3 int m_stredx ; 4 int m_stredy ; 5 public : 6 GrafickyObjekt ( int stredx, int stredy ){ 7 m_stredx = stredx ; 8 m_stredy = stredy ; 9 } 10 11 void vykresli (){ 12... 13 } 14 };
Konstruktory a destruktory Strana 15 / 22 Dědičnost a konstruktory: příklad (2) 1 class Kruh : public GrafickyObjekt { 2 private : 3 int m_polomer ; 4 public : 5 Kruh ( int stredx, int stredy, int polomer ): 6 GrafickyObjekt ( polomer ) 7 { 8 m_polomer = polomer ; 9 } 10 11 void vykresli (){ 12... 13 } 14 };
Konstruktory a destruktory Strana 16 / 22 Dědičnost a destruktory Destruktory se stejně jako konstruktory nedědí. Na rozdíl od konstruktorů se volají v opačném pořadí. (Od destruktoru aktuální třídy po destruktor nejvzdálenějšího předka.)
Shrnutí Strana 17 / 22 Obsah přednášky 1 Časná a pozdní vazba 2 Rozhraní pro dědičnost 3 Konstruktory a destruktory 4 Shrnutí
Shrnutí Strana 18 / 22 Co je to tedy ten polymorfismus? Objekty dvou tříd mohou mít metodu se stejným názvem, ale rozdílnou implementací. Příkladem je metoda vykresli() u příkladu s graf. objekty, vratzatez() u příkladu s auty, aj. Polymorfismus je využíván v souvislosti s pozdní vazbou vytvoříme si ukazatel na obecného předka, dosazujeme různé potomky a voláme metody definované ve společném rozhraní.
Shrnutí Strana 19 / 22 Shrnutí (co je důležité si pamatovat) Uvědomit si rozdíl mezi časnou a pozdní vazbou. Co je to čistě virtuální metoda a abstraktní třída. (Význam dědičnosti pro definici rozhraní.) Proč je důležitý virtuální destruktor. Jakým způsobem se chovají konstruktory a destruktory při dědění.
Shrnutí Strana 20 / 22 Příklady k procvičení Programátor-manažer Mějme firmu a v ní jsou tři druhy zaměstnanců programátoři, administrativa a manažeři. U všech zaměstnanců je evidováno jméno, početletnapozici... Všichni mají metody vratplat(). U programátora se počítá 30000+početLet*1000, u manažera 50000+početLet*1000, u administrativy 10000+početLet*1000. Dědičnost je nejsilnější vazba. De facto porušuje zapouzdření, protože změna v předkovi se promítá do potomků. Je to nepružná vazba, protože ji za běhu programu nelze měnit.
Shrnutí Strana 21 / 22 Příklady k procvičení: řešení? Zamestnanec Programator Manazer Administrativa Co když manažera povýší na programátora?
Shrnutí Strana 22 / 22 Příklady k procvičení: řešení? Zamestnanec 1 je zamestnan na PracovniPozice Programator Manazer Administrativa