Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Úvod do C# - OOP Jaroslav BURDYS 4IT.

Podobné prezentace


Prezentace na téma: "Úvod do C# - OOP Jaroslav BURDYS 4IT."— Transkript prezentace:

1 Úvod do C# - OOP Jaroslav BURDYS 4IT

2 Oběktově orientované Programování v C#

3 OOP - úvod Základní charakteristické znaky definující OOP (podrobněji viz dále): Zapouzdření (Enkapsulace) Dědičnost (Inheritance) Mnohotvarost (Polymorfizmus) Přestože je v C# vše objekt, plnohodnotnými objektovými typy z tohoto hlediska (tj. plnohodnotně implementujícími shora uvedenou trojí funkcionalitu) jsou v C# pouze refernční objektové typy (třídy) Hodnotové objektové typy (struktury) implementují plně pouze: zapouzdření dědičnost je silně omezena: Mohou dědit pouze od společného předka všech objektů: třida Object (toto lze ovšem obejít p-cí implementace rozhraní) Jsou to tzv. zapečetěné typy (sealed), tj. v jejich deklaraci nelze specifikovat předka a nelze od nich odvodit potomka Vzhledem k tomu, že u nich prakticky neexistuje dědičnost, nepodporují ani polymorfizmus přes dědičnost (toto lze opět obejít p-cí implementace rozhraní) Nemohou mít destruktory Nemohou mít uživatelem definovaný konstruktor bez parametrů Jejich konstruktory musí inicializovat všechny jejich datové složky Není-li definován uživatelem žádný konstruktor, překladač vytvoří konstruktor bez parametrů, který všechny datové složky inicializuje na: 0, false, null

4 Třída vs struktura Třída je v C# objektový typ typu reference => p-cí new lze vytvářet pouze dynamické objekty (o jejichž rušení se stará garbage collector), tj. jméno objektu třídy je vlastně pouze ukazatel na instanci dané třídy vytvořené na haldě => => na rozdíl od objektů hodnotových typů (např. struktury) kopírováním objektů třídy nevytváříme nový objekt, ale pouze nový ukazatel na ten samý objekt v paměti !!!. Např.: HODNOTOVÝ TYP vs REFERENČNÍ TYP struct Bod {int x; int y} class Bod {int x; int y} Bod A = new Bod(); Bod A = new Bod(); Bod B = A; Bod B = A; Co vzniklo v paměti: Co vzniklo v paměti: B.x = 5; //změní x v B B.x = 5; //změní x v A !!! Objekt A Ukazatel A Objekt Objekt B Ukazatel B

5 Zapouzdření (Encapsulation)
Zapouzdřením se v OOP označuje: 1) společné zastřešení dat i funkcionality (metod pracujících s těmito daty) v rámci jednoho datového typu (třídy) a tím přímo v samotné datové struktuře (objektu) daného typu 2) možnost ovlivňovat pomocí přístupových práv, odkud přesně z kódu bude příslušný datový typ (třída) a/nebo jeho složky (členská data a metody) přístupné

6 Zapouzdření – přístupová práva
Přístupnost složek v rámci samotného datového typu (třídy), jeho potomků (odvozených tříd), seskupení (assembly) či celého kódu (všech programů) určujeme pomocí tzv. modifikátorů přístupových práv: protected internal – přístupnost v rámci sestavy, ve které byla třída dané složky definována a zároveň i ve všech potomcích této třídy bez ohledu na jejich seskupení public – daná složka je dostupná nejen všem součástem aktuálního programu (assembly), ale i všem součástem všech programů (ostatním assembly) Modifikátor musí být uveden u každé složky třídy samostatně na rozdíl od C++,kde následující složky mají stejná práva jako první z nich, u které byl modifikátor uveden, dokud není u některé uveden jiný Není-li uveden žádný, je složka chápána implicitně jako private Je-li přístup složky širší než-li přístup samotné třídy, v níž se daná složka nachází, má přednost třída a přístupová práva složky budou zúženy na úroveň třidy Datový typ či jeho složka nesmí mít širší přístupová práva než kterýkoli z dalších typů uvedených v její deklaraci. Např.: Třída nesmí mít širší přístupová práva než její předek (bázová třída od které je odvozena) Metoda nesmí mít širší přístupová práva než typ, který vrací modifikátor třída seskupení potomci ostatní private internal protected protected internal public

7 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Třídu lze deklarovat dvojím způsobem: Samostatně v rámci jmenného prostoru

8 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Třídu lze deklarovat dvojím způsobem: Samostatně v rámci jmenného prostoru

9 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Třídu lze deklarovat dvojím způsobem: Samostatně v rámci jmenného prostoru Jako tzv. vnořenou v rámci jiné třídy jako jednu z jejích složek

10 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Třídu lze deklarovat dvojím způsobem: Samostatně v rámci jmenného prostoru Jako tzv. vnořenou v rámci jiné třídy jako jednu z jejích složek Je součástí vnější třídy => vztahují se na ní stejná přístupová práva jako na ostatní složky vnější třídy Složky vnitřní třídy MOHOU přistupovat k složkám vnější třídy (i soukromým) Složky vnější třídy NEMOHOU pracovat s nepřístupnými složkamy vnitřní třídy

11 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida

12 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract vytváří abstraktní třídu, tj. třídu natolik obecnou, že nelze implementovat její metody (nevytváří ani své vlastní instance), implementují je ale její specifičtější potomci a využívají je ve svých vlastních instancích jako zděděné metody

13 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed vytváří zapečetěnou třídu, tj. třídu, od které nelze dědit

14 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new v potomkovi přepisuje (předefinuje) složku stejného jména (datový typ)/signatury (metody) zděděnou po předkovi

15 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new Oba typy modifikátorů lze kombinovat

16 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new Pro samostatně deklarované třídy lze však použít pouze tyto modyfikátory

17 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new Pro samostatně deklarované třídy lze však použít pouze tyto modifikátory

18 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new internal – takto deklarovanou třídu lze použít pouze v seskupení, ve kterém je deklarována

19 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new public – takto deklarovanou třídu lze použít ve všech seskupeních, tj. je přístupná z celého kódu

20 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new není-li uveden modifikátor přístupových práv – u samostatně deklarovaných tříd imlicitně internal internal

21 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida class SamostatnaTrida Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new private není-li uveden modifikátor přístupových práv – u vnořeně deklarovaných tříd imlicitně private internal

22 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida public SamostatnaTrida MyFunc() class SamostatnaTrida public ??? Co je na tomto kódu chybně?

23 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida public SamostatnaTrida MyFunc() class SamostatnaTrida public Návratový typ veřejně přístupné metody je deklarován samostatně ve jmenném prostoru s implicitním přístupovým právem, tj. jako internal internal

24 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida public SamostatnaTrida MyFunc() class SamostatnaTrida public !!!!!! => PORUŠENÍ PRAVIDLA: Datový typ či jeho složka nesmí mít širší přístupová práva než kterýkoli z dalších typů uvedených v její deklaraci internal

25 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; Modifikátory přístupových práv private protected internal protected internal public Modifikátory dědičnosti (viz tam) abstract sealed new namespace DeklaraceTridy { class Program static void Main() } class VnorenaTrida public SamostatnaTrida MyFunc() class SamostatnaTrida public !!!!!! => PORUŠENÍ PRAVIDLA: Datový typ či jeho složka nesmí mít širší přístupová práva než kterýkoli z dalších typů uvedených v její deklaraci internal

26 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida class bazovaTrida

27 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida class bazovaTrida předek: A) identifikátor bázové třídy (přímého rodiče), od které je potomek odvozen (v případě potřeby kvalifikovaný jménem jeho prostoru jmen)

28 Zobecnění, jež je třeba doplnit
Deklarace třídy LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida: bazovaTrida class bazovaTrida předek: A) identifikátor bázové třídy (přímého rodiče), od které je potomek odvozen (v případě potřeby kvalifikovaný jménem jeho prostoru jmen) - v případě že není uveden použije překladeč společného předka všech tříd: třídu Object B) rozhraní, které se třída zavázala implementovat

29 Deklarace třídy – složky
LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class mojeTrida

30 Deklarace třídy - složky
LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class mojeTrida tělo: může být prázdné obsahuje specifikace složek třídy: deklarace členských dat definice metod uživatelem def.konstruktory uživatelem def.destruktor vlastnosti události implementace rozhraní (které se třída zavázala implementovat v části :předek) přetížené operátory

31 Deklarace třídy - složky
LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class mojeTrida specifikace složek třídy: DEKLARACE ČLENSKÝCH DAT: Deklarace datové složky (proměnné) již existujícího datového typu, včetně její inicializace. Definice nového datového typu, včetně nové, vnořené třídy. Deklarace datové složky vlastního typu (tj. své vlastní třídy). private int cislo = 15; public class vnorenaTrida{}; private mojeTrida dalsiMoje;

32 Deklarace třídy - složky
LEGENDA Ternární výraz Zobecnění, jež je třeba doplnit POVINNÉ NEPOVINNÉ modifikátory class identifikátor :předek {tělo}; namespace DeklaraceTridy { class Program static void Main() } class mojeTrida specifikace složek třídy: DEKLARACE ČLENSKÝCH DAT: Deklarace datové složky (proměnné) již existujícího datového typu, včetně její inicializace. Definice nového datového typu, včetně nové, vnořené třídy. Deklarace datové složky vlastního typu (tj. své vlastní třídy). Stejně jako v C++ lze inicializovat datové složky v těle konstruktoru přiřazení hodnoty pak nastane v době jeho volání (tj. v okamžiku vytváření instance) Na rozdíl od C++ lze inicializaci provést i přímo v těle třídy, přiřazení hodnoty pak proběhne: u nestatické složky při vytváření instance ještě před voláním konstruktoru u statické složky již v okamžiku zavedení třídy do paměti (tj. ještě před jejím prvním použitím) Není-li nějaká složka inicializována, nastaví ji překladač na hodnotu: 0, false, null private int cislo = 15; public class vnorenaTrida{}; private mojeTrida dalsiMoje; //toto v C++ nelze!

33 Dědičnost (Inheritance )
Umožňuje odvodit od existujícího datového typu typ nový a tím zefektivnit vytváření i editaci kódu Odvozený typ představuje zpravidla specializaci –tj. zvláštní případ – typu, od kterého byl odvozen => tzn. třída je typu „je jako…“ (např. Eskalátor vs Schodiště) na rozdíl od vnořené třídy, která je spíše typu „je obsažena v …“ (např. Eskalátor vs Budova) Na rozdíl od C++ podporuje C# pouze jednoduchou dědičnost, tj. potomek může mít pouze jednoho jediného přímého předka (bázovou třídu) Mnohonásobnou dědičnost lze v C# vytvořit p-cí jiných syntaktických konstrukcí (viz implementace rozhraní) Veškeré dědění v C# je veřejné (a to implicitně) tj. na rozdíl od C++ nemůžeme při dědění u jména rodiče používat modifikátory přístupu ani modifikátor virtual

34 Dědičnost (Inheritance )
Potomek zdědí všechny složky předka kromě: Konstruktorů (včetně statických) Destruktorů Zdědí i ty složky předka, ke kterým nemá přístupová práva, jen k nim pak nemá přístup: Privátní složky předka (deklarované v bázové třídě jako private ) Interní složky předka, je-li tento deklarován v jiném seskupení než dotyčný potomek (v bázové třídě jako internal) Uplatňuje se pravidlo, že potomek může vždy zastoupit předka => odkaz na potomka (tj. identifikátor jeho proměnné) můžeme použít všude tam, kde se očekává odkaz na jeho předka: tato vlastnost je základem polymorfizmu v OOP (viz tam) V C# lze polymorfizmu dosáhnout i bez dědičnosti, opět p-cí implementace rozhraní (viz tam)

35 Dědičnost (Inheritance )
Ke zděděným složkám může potomek přidat své vlastní Žádné však nemůže odstranit, pouze je může překrýt vlastní implementací p-cí klíčového slova new namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida: bazovaTrida new public void vypisSebe() Console.Write(„Jsem odvozená třída“); public void vypisPredka() base.Write(); class bazovaTrida public void vypisSebe() Console.Wite(„Jsem bázová třída“);

36 Dědičnost (Inheritance )
Ke zděděným složkám může potomek přidat své vlastní Žádné však nemůže odstranit, pouze je může překrýt vlastní implementací p-cí klíčového slova new V tom případě musí mít předefinovávaná složka stejný identifikátor (u datových typů) nebo signaturu (u metod) namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida: bazovaTrida {new public void vypisSebe() Console.Write(„Jsem odvozená třída“); public void vypisPredka() base.Write(); class bazovaTrida public void vypisSebe() Console.Write(„Jsem bázová třída“);

37 Dědičnost (Inheritance )
Ke zděděným složkám může potomek přidat své vlastní Žádné však nemůže odstranit, pouze je může překrýt vlastní implementací p-cí klíčového slova new V tom případě musí mít předefinovávaná složka stejný identifikátor (u datových typů) nebo signaturu (u metod) K původním rodičovským implementacím těchto složek pak může odvozená třída přistupovat (dovolují-li ji to přístupová práva) prostřednictvím kvalifikace klíčovým slovem base namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida: bazovaTrida new public void vypisSebe() Console.Write(„Jsem odvozená třída“); public void vypisPredka() base.vypisSebe(); class bazovaTrida public void vypisSebe() Console.Write(„Jsem bázová třída“);

38 Dědičnost (Inheritance )
Ke zděděným složkám může potomek přidat své vlastní Žádné však nemůže odstranit, pouze je může překrýt vlastní implementací p-cí klíčového slova new V tom případě musí mít předefinovávaná složka stejný identifikátor (u datových typů) nebo signaturu (u metod) K původním rodičovským implementacím těchto složek pak může odvozená třída přistupovat (dovolují-li ji to přístupová práva) prostřednictvím kvalifikace klíčovým slovem base namespace DeklaraceTridy { class Program static void Main() } class odvozenaTrida: bazovaTrida new public void vypisSebe() Console.Write(„Jsem odvozená třída“); public void vypisPredka() base.vypisSebe(); class bazovaTrida public void vypisSebe() Console.Write(„Jsem bázová třída“);

39 Polymorfizmus (mnohotvarost)
Jde o chování, kdy se v případě, že se na objekty libovolných potomků odkazujeme přes jejich společného předka, zavolá správná metoda příslušného potomka, tj. nikoli tedy rodiče, či jiného potomka. Je založen na dědičnosti a na tom, že potomek může vždy zastoupit předka => odkaz na potomka (tj. identifikátor jeho proměnné) můžeme použít všude tam, kde se očekává odkaz na jeho předka Polymorfizmus lze v C# vytvořit i bez použití dědičnosti p-cí implementace rozhraní (hlavně u datových typů, které nepodporují plnohod- notně dědičnost) Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); //přes rodiče Plachetnice L2 = new Plachetnice(); L1.pluj(); //přes rodiče L2.pluj(); } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

40 Polymorfizmus (mnohotvarost)
Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj Při volání přes odkaz na potomka vše proběhne v pořádku a zavolá se správná (předefinovaná) metoda potomka namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); L2.pluj(); } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

41 Polymorfizmus (mnohotvarost)
Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj Při volání přes odkaz na potomka vše proběhne v pořádku a zavolá se správná (předefinovaná) metoda potomka namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); L2.pluj(); //vypíše implementaci potomka } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

42 Polymorfizmus (mnohotvarost)
Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj Při volání přes odkaz na potomka vše proběhne v pořádku a zavolá se správná (předefinovaná) metoda potomka Při volání přes odkaz na předka se však nejprve volá konstruktor předka => použije se metoda předka (má-li stejnou signaturu), přestože je v potomkovi předefinována namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); L2.pluj(); //vypíše implementaci potomka } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

43 Polymorfizmus (mnohotvarost)
Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj Při volání přes odkaz na potomka vše proběhne v pořádku a zavolá se správná (předefinovaná) metoda potomka Při volání přes odkaz na předka se však nejprve volá konstruktor předka => použije se metoda předka (má-li stejnou signaturu), přestože je v potomkovi předefinována namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); //vypíše implementaci předka L2.pluj(); //vypíše implementaci potomka } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

44 Polymorfizmus (mnohotvarost)
Příklad: Vytvoříme bázovou třídu Lod Odvodíme od ní třídu Plachetnice a předefinujeme zděděnou metodu pluj Vytvoříme odkaz na potomka (Plachetnici) přes rodiče (Lod) Zavoláme přes ukazatel rodiče metodu pluj Při volání přes odkaz na potomka vše proběhne v pořádku a zavolá se správná (předefinovaná) metoda potomka Při volání přes odkaz na předka se však nejprve volá konstruktor předka => použije se metoda předka (má-li stejnou signaturu), přestože je v potomkovi předefinována namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); //vypíše implementaci předka L2.pluj(); //vypíše implementaci potomka } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“);

45 Polymorfizmus (mnohotvarost)
Příklad: Aby opravdu došlo k polymorfizmu a i přesto, že voláme potomka přes předka, se zavolala správná metoda příslušného potomka, musíme tyto (v potomcích pře- definované)metody u kterých má k polymorfizmu dojít deklarovat: v bázové třídě jako virtuální p-cí klíčového slova virtual Jako virtuální nesmějí být deklarovány: statické složky třídy (metody, vlastnosti, události) konstruktory a destruktory (v C++ destruktory mohou) a zároveň v odvozené třídě jako přepsané, tj. místo klíčového slova new použijeme klíčové slovo override NELZE kombinovat new a owerride ! LZE kombinovat new a virtual Polymorfizmus je velmi výhodný především v situacích, … : když předem nevíme s jakým typem potomka budeme pracovat: ke všem můžeme totiž vždy přistupovat přes ukazatel na jejich společného předka a přesto se díky polymorfizmu vždy zavolá správná metoda příslušného potomka když chceme stejně pracovat s různými druhy potomků najednou (např. přes iterace polem ukazatelů na jejich společného předka) namespace Lode { class Program static void Main() Lod L1 = new Plachetnice(); Plachetnice L2 = new Plachetnice(); L1.pluj(); L2.pluj(); //vypíše implementaci potomka } class Lod public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod new public void pluj() Console.WriteLine(„Plachetnice pluje“); virtual override

46 Dědičnost – abstraktní třídY
namespace Lode { class Program static void Main() } class Lod virtual public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, kteří již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují =>

47 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } class Lod virtual public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují =>

48 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } class Lod virtual public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují =>

49 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } class Lod virtual public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují =>

50 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } abstract class Lod virtual public void pluj() Console.WriteLine(„Lod pluje“); class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují => Abstraktní = plně virtuální, tj. metoda je sice deklarována v předkovi, ale definována (implementována) až v potomkovi (resp. specificky v každém potomkovi zvlášť)

51 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } abstract class Lod abstract public void pluj(); //abstraktní met. class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují => Abstraktní = plně virtuální, tj. metoda je sice deklarována v předkovi, ale definována (implementována) až v potomkovi (resp. specificky v každém potomkovi zvlášť)

52 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } abstract class Lod abstract public void pluj(); //abstraktní met. class Plachetnice: Lod owerride public void pluj() Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují => Abstraktní = plně virtuální, tj. metoda je sice deklarována v předkovi, ale definována (implementována) až v potomkovi (resp. specificky v každém potomkovi zvlášť) Abstraktní třída nemusí obsahovat žádnou abstraktní metodu Abstraktní metody se však mohou vyskytovat pouze v abstraktních třídách

53 Dědičnost – abstraktní třída
namespace Lode { class Program static void Main() } abstract class Lod abstract public void pluj(); //abstraktní met. } //defacto deklarace class Plachetnice: Lod owerride public void pluj() //implementace Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem abstract Vyjadřují pojmy, které jsou natolik abstraktní, že některou z metod pro ně nelze vůbec implementovat (nevytváří vlastní reálné instance/objekty), ale tyto abstraktní metody jsou zároveň společné pro všechny jejich specifičtější potomky, které již instance vytvářejí a přepsáním těchto zděděných abstraktních metod je pro sebe specificky implementují => Abstraktní = plně virtuální, tj. metoda je sice deklarována v předkovi, ale definována (implementována) až v potomkovi (resp. specificky v každém potomkovi zvlášť) Abstraktní třída nemusí obsahovat žádnou abstraktní metodu Abstraktní metody se však mohou vyskytovat pouze v abstraktních třídách

54 Dědičnost – zapečetěné třídy
namespace Lode { class Program static void Main() } abstract class Lod abstract public void pluj(); //abstraktní met. } //defacto deklarace class Plachetnice: Lod owerride public void pluj() //implementace Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem sealed

55 Dědičnost – zapečetěné třídy
namespace Lode { class Program static void Main() } sealed class Lod abstract public void pluj(); //abstraktní met. } //defacto deklarace class Plachetnice: Lod owerride public void pluj() //implementace Console.WriteLine(„Plachetnice pluje“); class Parnik: Lod Console.WriteLine(„Parnik pluje“); Deklarujeme je klíčovým slovem sealed Třídy od kterých nelze odvozovat potomky (=> zefektivnění kódu překladačem) Při použití s virtuální metodou získáme zapečetěnou metodu, tj. metodu, kterou nelze v potomkovi předefinovat POZOR: Lze pouze na straně metody deklarované jako override ! Nelze použít u metod: s modifikátorem virtual nevirtuálních abstraktních a u abstraktních tříd Používáme často u tříd, které obsahují pouze statické členy (právě z důvodu větší efektivity, např. systémová třída string) Všechny struktury jsou zapečetěné


Stáhnout ppt "Úvod do C# - OOP Jaroslav BURDYS 4IT."

Podobné prezentace


Reklamy Google