260 likes | 397 Views
Principy OOP. Objektově orientované programování vychá-zí ze třech základních principů (rysů): zapouzdření ( encapsulation ) dědičnost ( inheritance ) polymorfismus. Zapouzdření. Třída může obsahovat libovolné množství členů
E N D
Principy OOP • Objektově orientované programování vychá-zí ze třech základních principů (rysů): • zapouzdření (encapsulation) • dědičnost (inheritance) • polymorfismus
Zapouzdření • Třída může obsahovat libovolné množství členů • Při správném objektově orientovaném přístu-pu by však měla být data skryta (zapouzdřena) uvnitř třídy • K jednotlivým objektům by se mělo přistupo-vat prostřednictvím metod nebo vlastností • Toto snižuje nebezpečí vzniku chyby a umož-ňuje tvůrci modifikovat vnitřní reprezentaci třídy
Dědičnost (1) • Jedná se o prostředek, který umožňuje dosáh-nout snadné rozšiřitelnosti a znovupoužitel-nosti již existujících částí programu • Dovoluje definovat novou třídu (B), která vznikne pouze přidáním nových členů k těm, které již byly definovány v rámci jiné třídy (A) • Třída: • A se stává bezprostředním předkem třídy B • B je bezprostředním potomkem třídy A
Dědičnost (2) • Nechť je dána třída:class Date{public byte Day {get; set; }public byte Month {get; set; }public short Year {get; set; }public Date(byte d, byte m, short y){…}public string GetDate(){…}public bool IsLeapYear(){…}} • Na jejím základě lze definovat jejího potomka
Dědičnost (3) • Informace o bezprostředním předkovi se zapi-suje v definici třídy (za jejím názvem – oddě-lena dvojtečkou) • Příklad:class DateExt : Date{public DateExt (byte d, byte m, short y) : base(d, m, y) {…}publicvoid AddDay() {…}publicvoid SubtractDay() {…}privatebyte GetMonthDaysCount() {…}}
Dědičnost (4) • Jestliže třída B je potomkem třídy A, tak jsou třídě B automaticky dostupné všechny členy (vyjma konstruktorů instancí, statických kon-struktorů a destruktorů) třídy A, aniž by bylo nutné je znovu definovat • Říkáme, že třída B dědí členy třídy A • Jestliže při definici třídy v jazyku C# neuve-deme žádného předka, je jejím předkem auto-maticky třída object(System.Object)
Dědičnost (5) • Každá definovaná třída automaticky dědí členy definované ve třídě object, např. metody: • Equals: • zjistí, zda jsou si dvě instance typu object rovny • GetHashCode: • vrací hash kód objektu, který slouží k efektivnímu vyhledávání v hashových tabulkách • ToString: • vrací textovou reprezentaci objektu • Zděděné datové položky bývají obvykle inicia-lizovány vyvoláním konstruktoru předka
Dědičnost (6) • Konstruktor předka se volá pomocí klíčového slova base, které je uvedeno za hlavičkou konstruktoru potomka (odděleno dvojtečkou) • Příklad:publicDateExt(byte d, byte m, shorty): base(d, m, y) {…} • Pokud volání konstruktoru předka není expli-citně provedeno, pak zkouší překladač volat konstruktor implicitní
Dědičnost (7) • Tj. definice:public DateExt(byte d, byte m, short y){…}bude automaticky přepsána (doplněna) na tvar: public DateExt(byte d, byte m, short y): base() {…} • Doplněný tvar je funkční pouze v případě, že předek obsahuje (má v programu definovaný) veřejný implicitní konstruktor (v opačném případě dojde k chybě při překladu)
Dědičnost (8) • Skrývání (maskování) metod: • dovoluje na úrovni potomka definovat metodu, která má stejnou signaturu (stejné jméno, stejný počet a typy formálních parametrů) jako metoda na úrovni předka • metoda potomka tak skrývá (maskuje) metodu předka • metody, které provádějí skrývání by měly být de-finovány pomocí klíčového slova new (v opač-ném případě bude překladač vypisovat varování)
Dědičnost (9) • Platí, že proměnné typu třída A (předchůdce) je možné přiřadit proměnnou typu třída B (následníka) – opačné přiřazení není možné • Lze provést přiřazení tvaru: objekt předka = objekt potomka; • Příklad:Date d = new Date(1,1,2000);DateExt dExt = new DateExt(2,8,2010);d = dExt;
Polymorfismus (1) • Rys umožňující, aby akce uskutečňované nad různými objekty byly pojmenovány stejně, přičemž ale jejich realizace je různá (podle toho, nad kterým objektem se provádějí) • Nástrojem pro realizaci polymorfismu jsou tzv. virtuální metody • Virtuální metody: • obsahují ve své definici klíčové slovo virtual • implementace virtuálních metod může být na úrovni potomka nahrazena implementací jinou
Polymorfismus (2) • umožňují volat různé verze stejné metody na zá-kladě typu objektu určeného dynamicky za běhu programu • proces nahrazení implementace zděděné virtuální metody se označuje jako předefinování (potlačení, overriding) metody • metoda realizující odlišnou implementaci na úrov-ni potomka musí ve své definici obsahovat klíčové slovo override • nová implementace metody (na úrovni potomka) může volat původní implementaci téže metody (na úrovni předka) pomocí klíčového slovabase, jež se zapisuje v příkazové části metody
Polymorfismus (3) • poznámky: • klíčová slova virtual a override nelze použít u soukromých (privátních) metod • signatura metody, která provádí předefinování, musí být stejná (včetně návratového typu) jako signatura původní metody • metoda s klíčovým slovem override je rovněž vir-tuální a může být na úrovni dalšího potomka opět pře-definována
Skrytí vs. předefinování • Skrytí: • jedna metoda nahrazuje metodu jinou • tyto metody obvykle nemají žádnou vazbu a mo-hou provádět zcela odlišné úlohy • Předefinování: • zajišťuje různé implementace stejné metody • všechny implementace jsou příbuzné – provádě-jí v zásadě stejnou úlohu, ale specifickým způ-sobem pro danou třídu
Abstraktní metody a třídy (1) • Jazyk C# dovoluje definovat tzv. abstraktní metody • Abstraktní metoda se definuje pomocí klíčové-ho slova abstract a neobsahuje žádnou im-plementaci • Abstraktní metody jsou automaticky virtuální (klíčové slovo virtual se však neuvádí) • Třída, jež obsahuje abstraktní metodu se ozna-čuje jako abstraktní třída a musí být rovněž de-finována s klíčovým abstract
Abstraktní metody a třídy (2) • Na základě abstraktní třídy nelze vytvořit no-vou instanci: • slouží pouze jako třída, na jejímž základě budou definovány další třídy (jako její potomci) • Potomci abstraktní třídy provádějí předefino-vání abstraktních metod (pomocí klíčového slova override), čímž doplňují jejich imple-mentaci • Poznámka: • jako abstraktní mohou být také označeny vlastno-sti, indexery a události
Abstraktní metody a třídy (3) • Příklad:abstractclassShapesClass{abstractpublic doubleGetArea(); } classSquare : ShapesClass{private doubleside; public Square(doublen) {side= n; }public override doubleGetArea() {returnside * side; }}
Rozhraní(1) • Rozhraní (interface) definuje kontrakt s třídou nebo strukturou, která je následně od tohoto rozhraní odvozena • Představuje seznam členů, které se odvozená třída nebo struktura zavazuje implementovat • Platí, že: • jedno rozhraní může dědit od jednoho nebo více jiných rozhraní • jedna třída může implementovat jedno nebo více rozhraní (může dědit pouze od jedné třídy) • Dovoluje „nahradit“ vícenásobnou dědičnost
Rozhraní(2) • Umožňují třídám přidávat charakteristiky nebo schopnosti nezávisle na hierarchii tříd • Rozhraní může obsahovat: • metody • události • vlastnosti • indexery • Definice rozhraní: • začíná klíčovým slovem interface, za nímž následuje jméno rozhraní • obsahuje pouze signatury členů (nikoliv jejich implementace)
Rozhraní (3) • Všechny členy jsou automaticky veřejné (ma-jí přístupnost public): • klíčové slovo public se neuvádí • rozhraní udává, jak s objektem zvenku pracovat • Jméno implementovaného rozhraní se zapisu-je za jméno třídy oddělené dvojtečkou • Konvence: • jména rozhraní se zapisují s počátečním velkým písmenem I • Poznámka: • od rozhraní nelze vytvořit instanci
Rozhraní (4) • Příklad:interfaceIPoint{intX { get; set; }intY { get; set; }voidWritePointCoords();}classMyPoint : IPoint{public intX { get; set; }public intY { get; set; }publicMyPoint(int x, int y){X = x; Y = y; } public voidWritePointCoords(){Console.WriteLine(”[{0}, {1}]”, X, Y);}}
Rozšiřující metody • Umožňují rozšířit existující datový typ (třídu nebo strukturu) dodatečnými statickými me-todami • Tyto metody jsou okamžitě k dispozici jakým-koliv příkazům, které se odkazují na data roz-šířeného typu • Definují se ve statické třídě • Typ, kterého se rozšiřující metoda týká, se uvádí jako první parametr metody společně s klíčovým slovem this
Podmíněný operátor (1) • Ternární operátor umožňující zkrácený zápis příkazové struktury if…else • Umožňuje vyhodnotit podmínku a vrátit jednu hodnotu v závislosti na tom, je-li podmínka splněna nebo nesplněna • Zapisovaný ve tvaru:podmínka?splněno:nesplněnokde: • podmínka: • booleovský výraz, který se vyhodnotí
Podmíněný operátor (2) • splněno: • hodnota, která se vybere v případě splnění podmínky • nesplněno: • hodnota, která se vybere vpřípadě nesplnění podmínky • Příklad:intx;string s=x.ToString()+” ”;s+=(x==1?”člověk”:”lidé”);Console.WriteLine(s);