Základy objektově orientovaného programování (OOP) Obsah Obsah..................................................................................................................................................................... 1 Cíl kapitoly ........................................................................................................................................................... 1 Jazyky procedurální a objektově orientované ............................................................................................... 2 Pojem objekt ........................................................................................................................................................ 2 Pojem třída ........................................................................................................................................................... 4 Znázornění třídy v diagramech UML .............................................................................................................. 6 Zapouzdření ......................................................................................................................................................... 6 Skrývání informací a implementací ................................................................................................................ 7 Zachování stavu ................................................................................................................................................... 8 Identita objektu ................................................................................................................................................... 8 Zprávy ................................................................................................................................................................... 8 Metody .................................................................................................................................................................. 9 Specifikátory přístupu ..................................................................................................................................... 10 Prostředky pro OOP v C# ................................................................................................................................ 11 Vytvoření instance třídy (objektu) příkazem new ...................................................................................... 11 Statické a nestatické metody a proměnné .................................................................................................... 12 Funkce konstruktor ........................................................................................................................................... 14 Vytvoření pole objektů .................................................................................................................................... 16 Přiřazování objektů .......................................................................................................................................... 17 Třídní data a třídní metody ............................................................................................................................. 18 Předávání objektů metodám přes parametry ............................................................................................... 19 Vracení objektů metodami .............................................................................................................................. 21 this – odkaz na aktuální instanci .................................................................................................................... 21 Kompozice .......................................................................................................................................................... 22 Vlastnosti ............................................................................................................................................................ 25 Otázky z probrané látky .................................................................................................................................. 27 Příklady ............................................................................................................................................................... 28 Seznam programů .............................................................................................................................................. 40 Seznam obrázků ................................................................................................................................................. 41 Literatura ............................................................................................................................................................. 41
Cíl kapitoly Cílem kapitoly.je seznámit žáky se základy objektově orientovaného programování, se základními pojmy (objekt, třída, zapouzdření, metody). Probíraná látka je ilustrovaná příklady programů v jazyku C#.
2.11.11
Základy objektově orientovaného programování (OOP)
1/41
Klíčové pojmy:
Objekt, třída, diagram UML, zapouzdření, metody, specifikátory přístupu, konstruktor, this, kompozice, vlastnosti
Jazyky procedurální a objektově orientované Jedno hledisko dělení programovacích jazyků je na: procedurální a objektově orientované. Procedurální programování Ve většině tradičních procedurálních jazyků, jako je Pascal, Fortran, BASIC, PL1, C a COBOL, je program rozdělený na kód a data. Kód pro zpracování dat představují funkce (procedury, metody), data mohou být uložena v samostatných proměnných, nebo sloučena do polí a struktur. Programátoři během celé historie programování často usilovali o uspořádání kódu a dat, zejména u delších programů pro zvýšení jejich přehlednosti. Související funkce mohly být seskupeny dohromady v témže souboru zdrojového kódu. Tento soubor mohl obsahovat proměnné, které jsou používány těmito funkcemi a nikde jinde v programu. Související data bylo možné sloučit do struktur a polí.
Pojem objekt V objektově orientovaném programování (OOP) pracujeme s objekty, čímž napodobujeme reálný svět. Objekt je entita (věc), která má svou identitu (každý objekt lze jednoznačně odlišit od objektu jiného jeho názvem) a své vlastnosti (každý objekt má nějaký vnitřní stav a nějak se chová vůči svému okolí). V reálném světě jsou objekty hmotné, mají materiální podstatu. V programování může objekt představovat abstraktní pojem. Objektově orientovaný program užívá objekty, čímž napodobuje realitu. Příklady objektů: strom, auto, člověk, datový soubor, okno v grafickém operačním systému, tlačítko v grafickém operačním systému, různé datové struktury jako je pole, fronta, zásobník atd. databázové připojení 2.11.11
Základy objektově orientovaného programování (OOP)
2/41
faktura zaměstnanec Každý objekt, který má být užitečný, musí poskytovat svému okolí nějaké služby. Například: auto se umí rozjet, zastavit atd. okno v grafickém operačním systému se umí minimalizovat, zavřít, aktivovat, atd. datový soubor se umí otevřít, zavřít, lze do něj zapsat, lze z něj číst. Modulární přístup v OOP Program lze dekomponovat (rozložit) na menší části (moduly), které provádí konkrétní dílčí úkoly. Na takové moduly (objekty) se můžeme dívat jako na černé skříňky, které mají definované rozhraní (vstupy a výstupy) a uživatele nezajímá vlastní obsah této černé skříňky. Uživatel se nezajímá, jakým způsobem objekty služby poskytují, ale zajímá se jen, jaké služby poskytují. Výhody modulárního přístupu: Uživatel se nemusí starat o vnitřek modulu (objektu), přistupuje k němu jako k celku pomocí rozhraní (definovaných vstupů a výstupů) Pokud má modul stejné rozhraní (vstupy a výstupy), lze jej jednoduše vyměnit za jiný, aniž by to uživatel modulu poznal V OOP se vytváří objekty, které mají definované rozhraní, a vnitřek je ukryt. Objekty se mohou vyměňovat za lepší bez zásahů do programů, které je používají. Objektově orientovaný program je srozumitelnější a lze ho lépe spravovat. Aktualizace se obvykle týká jen několika objektů, zbytek lze ponechat v původním stavu. Procedurální styl programování umožňoval zpočátku rychlý vývoj aplikací, ale jejich správa a modifikace byly náročné, neboť bylo nutné zasáhnout na mnoho míst v programu. V OOP se nejprve navrhují jednotlivé třídy a potom už se skládá skládačka z objektů, objekty začínají komunikovat a vývoj je rychlý a lehce upravovatelný. Hlavní cíl v OOP je vytipovat objekty, které řeší dílčí úkoly a definovat vhodné rozhraní objektů pro jejich vzájemnou komunikaci. Na objekt se můžeme dívat jako na složitou proměnnou, která má určité vlastnosti a můžeme s ní provádět určité operace. Například s proměnnými typu int a double můžeme provádět aritmetické operace, které s proměnnými typu char provádět nemůžeme. Objekt typu Učitel má určité vlastnosti a můžeme s ním provádět určité operace, které jsou jiné, než pro objekt typu Student. Objekty jsou všudypřítomné stavební bloky moderního softwaru. 2.11.11
Základy objektově orientovaného programování (OOP)
3/41
Objekt představuje zjednodušený pohled na skutečný předmět. Současná tvorba softwaru je orientovaná na objekty. Program v OOP je množina mezi sebou navzájem komunikujících objektů. OO software (SW) je takový SW, který obsahuje objekty a třídy, do nichž patří. Objektyjsou SW konstrukce, v níž jsou operace(metody) uspořádány kolem množiny proměnných (dat). Každý objekt má vlastní kopie proměnných, definovaných v jeho třídě. Pro všechny objekty určité třídy existuje společná množina metod, použitelná pro všechny objekty. Následující obrázek znázorňuje tři objekty jedné třídy, z nichž každý má 7 vlastností (atributů) a můžeme s ním pracovat pomocí čtyř metod (funkcí). OBJ 1 Prom. A1 Prom. A2 Prom. B1 Prom. B2 Prom. C1 Prom. C2 Prom. D1
OBJ 2 Prom. A1 Prom. A2 Prom. B1 Prom. B2 Prom. C1 Prom. C2 Prom. D1
OBJ 3 Prom. A1 Prom. A2 Prom. B1 Prom. B2 Prom. C1 Prom. C2 Prom. D1
met A met B met C met D
Obrázek 1 Ilustrace objektů, atributů a metod
Objekty mají své vlastní atributy (proměnné) a společné operace (metody). Proměnné má každý objet má své vlastní a metody jsou sdílené všemi objekty co vede k úspoře paměti. Metody (funkce) můžeme spouštět pomocí objektů, nebo pomocí ukazatelů na objekty. Kromě atributů a metod, které jsou vázané na objekty existují i atributy a metody, vázané na třídu (třídní metody a data). Takovým třídním atributem může být proměnná, která uchovává počet vytvořených objektů.
Pojem třída V objektově orientovaném programování vzniká nový pojem – třída. Třída definuje spojení metod a atributů skutečných objektů. Můžeme si ji představit jako formičku, podle které se vytváří bábovičky. Je to nový, složitější datový typ, zahrnující v sobě jak data, tak kód, který s těmito daty pracuje (metody). 2.11.11
Základy objektově orientovaného programování (OOP)
4/41
Třída objektů je abstrakce množiny podobných objektů. Objekt je fiktivní proměnná, jejíž struktura odpovídá struktuře třídy a může používat metody třídy. Třída (class) je nový datový typ, který můžeme použít pro definování objektů stejně jako základní datové typy můžeme použít pro definování celočíselných, nebo znakových proměnných. Třída představuje typ, který definuje množinu objektů, popisuje objekty se společnými vlastnostmi a chováním. Všechny objekty konkrétní třídy mají stejné vlastnosti (atributy, proměnné) – liší se jen hodnotami datových položek. Na všechny objekty konkrétní třídy můžeme použít stejné metody. Vztah objektu ke třídě vyjadřuje definice: objekt je instance třídy. Ve třídě dochází ke sloučení dat a metod pod jedno jméno co se nazývá zapouzdření. Chceme-li programovat objektově, musíme:
nejprve definovat abstraktní model – jakoby nový, složitější datový typ (tj. strukturu, nebo třídu). Potom definujeme konkrétní objekty – jakoby „složitější“ proměnné definovaného typu.
Programátor může být: autor tříd uživatel tříd Třída popisuje skupinu objektů se stejnými vlastnostmi (datové prvky) se stejným chováním (funkce) Programátor definuje třídu tak, aby ji přizpůsobil řešenému úkolu. Shrnutí: Třída je vzor či šablona sloužící k vytváření objektů - forma, podle které se vytvářejí objekty (instance třídy) Některé objekty mají mnoho společných vlastností - jsou stejné třídy. Je-li objekt vytvořený podle nějaké třídy, nazývá se instancí této třídy. Každá třída může mít libovolný počet instancí. Třída je nástroj, kterým objektově orientovaný jazyk umožňuje převést abstrakci do uživatelem definovaného typu. Třídy kombinují data a metody pro manipulaci s daty. Každý objekt má stejnou strukturu a chování jako třída, jejíž je instancí. Patří-li objekt obj do třídy T, pak říkáme, že obj je instancí T. Objekty jedné třídy se liší: identifikátorem 2.11.11
Základy objektově orientovaného programování (OOP)
5/41
stavem (hodnotami, uloženými v proměnných objektu) Rozdíl mezi třídou a objektem: třída je to, co navrhujete a programujete objekty jsou to, co vytváříte (ze třídy) při běhu aplikace
Znázornění třídy v diagramech UML Jméno třídy
Atributy
Obrázek 2 Diagram UML, znázorňující třídu
Metody
Nejdůležitější vlastnosti OOP:
Abstrakce Zapouzdření Skrývání informací a implementací Zachování stavu Identita objektu Zprávy Polymorfismus - mnohotvarost Dědičnost Znovupoužitelný kód
Abstrakce Zaměření se na objekty nám usnadňuje pochopení složitých věcí. Objekty nám umožňují soustředit se na záležitosti, které nás zajímají a ignorovat to, co pro nás není podstatné. Abstrakce je odstranění nepodstatných rysů a soustředění se na hlavní znaky umožňuje redukovat složitost. Abstrakci nám umožňují třídy a objekty.
Zapouzdření Zapouzdření je způsob propojení atributů (data) a metod (funkcí) pro vytvoření objektu. 2.11.11
Základy objektově orientovaného programování (OOP)
6/41
Zapouzdření umožňuje programátorovi umístit atributy a metody do třídy a následně definovat pravidla ve třídě pro řízení přístupu. Zapouzdření je seskupení souvisejících položek do jedné jednotky, na kterou se lze následně odkazovat jedním názvem. Je to stará koncepce. Zapouzdření příkazů umožňovaly podprogramy a funkce (40. léta). Zapouzdřením algoritmu do funkce se umožní opakované volání funkce na různých místech programu - tzv. znovupoužití kódu. Objektově orientované (OO) zapouzdření OO zapouzdření umožňuje ještě vyšší úroveň znovupoužití objektů. Zapouzdřený objekt obsahuje nejen metody, ale i data, která uchovávají stav objektu. V terminologii OOP se data objektů nazývají atributy. OO zapouzdření představuje zabalení metod a atributů do jednoho typu objektu, takže daný stav je přístupný pouze prostřednictvím rozhraní poskytovaného zapouzdřením. Zapouzdření poskytuje rozhraní, kterým je možné natavit/číst stav objektu. Tím rozhraním jsou odpovídající metody (funkce).
Skrývání informací a implementací Pohledy na zapouzdřenou jednotku mohou být: veřejný (z vnějšku) soukromý (z vnitřku) Dobré zapouzdření odstraňuje podrobností z vnějšího pohledu Potlačení podrobností má 2 formy: skrývání informací skrývání implementací (jak je to realizováno) Uživatel ví , co dokáže objekt udělat ale neví jak.to dělá. Významy skrývání : lokalizace rozhodnutí návrhu – návrh může být později aktualizován bez vědomí uživatele třídy ruší vazbu mezi obsahem informací a formou jejich reprezentace. Co představuje skrývání informací a implementací a jaký má význam? brání v přímém přístupu k položkám třídy uživatele zprošťuje potřeby znát reprezentaci dat – implementace je oddělena od návrhu rozhraní.
2.11.11
Základy objektově orientovaného programování (OOP)
7/41
Jestliže návrhář třídy najde později lepší způsob reprezentace dat nebo implementace metod, může tyto detaily změnit bez nutnosti změny rozhraní třídy, což velmi zjednodušuje údržbu programu. Veřejné nebo privátní Položky třídy jsou: datové nebo metody (funkce) Položky lze uvést v části: veřejné (public) privátní (private) chráněné (protected) Datové položky třídy se obvykle uvádí v privátní části třídy. Členské funkce tvořící rozhraní třídy se uvádí ve veřejné části třídy- jinak byste je nemohli volat z vnějšku třídy. Členské funkce lze uvést i v privátní části – ty potom nelze volat přímo z části programu mimo třídu, ale mohou je volat metody stejné třídy.
Zachování stavu Objekt si je vědom své minulosti. Stav je množina hodnot, které objekt uchovává. Tradiční procedurální modul (funkce, podprogram) po provedení kódu přestane existovat a jako odkaz ponechá jen svůj výsledek. Jak se stav uchovává je interní záležitost třídy – programátor volí atributy a způsob práce s nimi..
Identita objektu Každý objekt je jedinečný – to zajišťuje jeho identifikátor. Pro identifikátor platí: zůstává nezměněn po celou dobu existence objektu a je jedinečný.
Zprávy OOP je založeno na výměně zpráv mezi objekty. V objektově navrženém programu objekty spolu komunikují – zasílají si zprávy a reagují na ně. Jeden objekt může požádat druhý objekt, aby načetl data ze souboru a třetí objekt, aby data zobrazil v okně. Zápis v jazyku UML 2.11.11
Základy objektově orientovaného programování (OOP)
8/41
zpráva
Objekt Obrázek 3 Předání zprávy objektu
Zpráva je metoda (funkce) třídy. Metoda je společná všem objektům této třídy. Zpráva (message) je prostředek, kterým odesílající objekt přenáší cílovému objektu požadavek, aby cílový objekt použil jednu ze svých metod. Struktura zpráv Odesílající objekt (klient, odesílatel, sender ) musí znát: identifikátor cílového objektu název operace cílového objektu další dodatečné informace (argumenty metod) Zprávy lze “rozšířit“ argumenty Argumenty zpráv mohou být: vstupní výstupní Role objektů ve zprávách: odesílatel cíl obojí Termín odesílatel a cíl jsou relativní vzhledem k dané zprávě. Typy zpráv: informační – aktualizační dotazovací – čtecí: požaduje informaci po objektu přikazovací – akční:požaduje po objektu vykonání akce
Metody Objekt je vždy obklopen jinými objekty, kterým poskytuje svoje služby a po kterých služby požaduje. Požadavku na provedení služby se říká zpráva. Po zaslání zprávy objektu zprávu, nastane jeden ze dvou případů: Objekt zprávě rozumí (je schopen ji přijmout.) a zareaguje na ni nějakou svou metodou.
2.11.11
Základy objektově orientovaného programování (OOP)
9/41
Objekt zprávě nerozumí a nijak nezareaguje, případně jako svou reakci oznámí uživateli, že není schopen zprávu přijmout. Množina zpráv, které objekt může přijmout, se nazývá rozhraní (interface). Popisu, jakým způsobem lze objektům zasílat zprávy (pořadí a podobně), se nazývá komunikační protokol objektu. Například datový soubor lze nejprve otevřít pro zápis, až poté do něj zapisovat, poté jej zase zavřít. K datům (atributům) v objektu lze přistupovat jen pomocí rozhraní - vyvoláním metod. Tento jev se nazývá zapouzdření dat. Program napsaný v OOP je vlastně množina mezi sebou navzájem komunikujících objektů. Pojmu metoda se také někdy říká členská funkce - je to funkce, která není globální, ale je volatelná jen v souvislosti s instancemi dané třídy. Někteří autoři [7] doporučují při návrhu tříd vyjít z textové analýzy zadání: podstatná jména jsou kandidáti tříd slovesa jsou kandidáti metod
Specifikátory přístupu Specifikátor přístupu je klíčové slovo programovacího jazyka, které říká počítači, jaká část aplikace může přistupovat k datům a metodám třídy. Specifikátor veřejného přístupu Specifikátor veřejného přístupu označuje atributy a metody, které jsou přístupné metodami nacházejícími se uvnitř i vně třídy. Specifikátor privátního přístupu Specifikátor privátního přístupu označuje atributy a metody, které jsou přístupné pouze metodami definovanými téže třídy. Specifikátor chráněného přístupu Specifikátor chráněného přístupu určuje atributy a metody, které mohou být zděděny a použity jinou třídou. Programátoři vyžadují, aby se k některým atributům třídy dalo přistupovat pouze prostřednictvím členské funkce neboli metody. Je to proto, aby bylo možném ověřit hodnoty přiřazené do těchto atributů. Programátor, který chce získat přístup k určitým atributům, volá metodu a ta před přiřazením hodnot atributům uplatní všechna pravidla ověřování. Na obrázku Obrázek 2 je UML diagram, znázorňující třídu, její atributy a metody.
2.11.11
Základy objektově orientovaného programování (OOP)
10/41
Je-li atribut veřejný, píšeme před něj znaménko +, je-li soukromý, píšeme - , je-li atribut chráněný, píšeme před něj #.
Prostředky pro OOP v C# K vytvoření třídy slouží klíčové slovo class Definice vypadá následovně: modifikátorynep class NázevTřídy : předeknep { Položky třídy }; Index nep označuje nepovinnou položku. Položky mohou být soukromé (private), chráněné (protected) a veřejné (public). Soukromé položky mohou být proměnné, ke kterým mají přístup pouze metody dané třídy. Jsou zapouzdřeny, a přístup k nim se provádí jen přes veřejné rozhranní. Veřejné položky může využívat kdokoliv. Veřejné položky tvoří rozhraní objektu dané třídy. Jako veřejné položky by neměly být proměnné, protože by docházelo k porušení zapouzdření. Chráněné položky jsou přístupné v rámci dané třídy a z objektů podle tříd děděných z dané třídy. Jak se liší struktury a třídy? Liší se potřebou použít modifikátory public a private pro určení viditelnosti následující vlastnosti, nebo metody. Uvnitř struktury je vše implicitně veřejné, uvnitř třídy je vše implicitně soukromé. Programátoři v C# používají třídy k implementaci popisů metod i dat, zatímco struktury se používají k reprezentaci čistě datových objektů.
Vytvoření instance třídy (objektu) příkazem new S objekty pracujeme pomocí tzv. odkazů, referencí. Deklarace: Učitel Petr nevytvoří objekt třídy Učitel, ale odkaz na ni. Tento odkaz ovšem zatím na žádnou instanci neodkazuje. 2.11.11
Základy objektově orientovaného programování (OOP)
11/41
K vytvoření nové instance nám v C# slouží příkaz new, za nímž zapíšeme volání speciální metody - konstruktoru, která vytváří objekt například takto: Učitel Petr =new Učitel(); Tím vytvoříme objekt Petr třídy Učitel. Následující program v C# ukazuje definování třídy pro uložení hodnoty celého čísla a její použití. Program 1 Třída pro uchování celého čísla Definujte třídu, která bude obsahovat celočíselnou datovou položku Cislo a veřejné metody pro nastavení a vrácení jeho hodnoty. V definici třídy nezáleží na pořadí datových položek a metod. Před veřejnými položkami je třeba uvést specifikátor přístupu public. using System; class TridaCislo{ /*Položka Cislo je soukromá. */ int Cislo; /* Metoda vrátí hodnotu Cislo. */ public int VratMiTvojeCislo() { return Cislo; } /* Metoda nastaví hodnotu Cislo. */ public void NastavSiCislo(int noveCislo){ Cislo=noveCislo; } }; class Program { static void Main() { int a = 1; /* Vytvoření nového objektu TC třídy TridaCislo pomocí implicitního konstruktoru TridaCislo (). */ TridaCislo TC = new TridaCislo (); /* Nastavení hodnoty Cislo na hodnotu proměnné a metodou NastavSiCislo(a). */ TC.NastavSiCislo(a); /* Výpis hodnoty privátní proměnné Cislo. */ Console.WriteLine("{0}", TC.VratMiTvojeCislo()); Console.ReadLine(); } }
Statické a nestatické metody a proměnné Proměnná Cislo je proměnná, která je definována ve třídě TridaCislo . 2.11.11
Základy objektově orientovaného programování (OOP)
12/41
Každá instance této třídy bude obsahovat svou proměnnou Cislo. V čistě objektově orientovaném programu (jako je program v C#) neexistují globální funkce, ale jen statické metody. Metodu Main můžeme uvést do stejné třídy jako metody pro nastavení a vrácení čísla, a definici metod můžeme uvést před, nebo za Mainem. Je-li proměnná Cislo statická, můžeme k ní v Mainu přistupovat přímo, bez vytvoření objektu, jak ilustruje následující příklad. Program 2 Použití statické proměnné ve stejné třídě jako Main using System; class TridaCislo { static int Cislo=0; static void Main() { Console.WriteLine("{0}", Cislo); Console.ReadLine(); } }
Není-li proměnná Cislo statická, může k ní Main přistupovat pouze pomocí objektu: Program 3 Použití nestatické proměnné using System; class TridaCislo { /*Položka Cislo je soukromá.*/ int Cislo=1; static void Main() { TridaCislo TC = new TridaCislo (); Console.WriteLine("{0}", TC.Cislo); Console.ReadLine(); } }´
Program 4 Použití statické proměnné Cislo Jestliže v programu Program 1 použijeme statickou proměnnou Cislo, můžeme k ní přistupovat pomocí názvu třídy, operátoru tečka a názvu položky: TridaCislo.Cislo. using System; class TridaCislo { /*Položka Cislo je soukromá. */ static public int Cislo; /* Metoda vrátí hodnotu Cislo. */ }; class Program { 2.11.11
Základy objektově orientovaného programování (OOP)
13/41
static void Main() { /* Nastavení hodnoty Cislo na hodnotu proměnné Cislo */ TridaCislo.Cislo=10; /* Výpis hodnoty proměnné Cislo. */ Console.WriteLine("{0}", TridaCislo.Cislo); Console.ReadLine(); } }
Funkce konstruktor Konstruktor je speciální metoda, která je volaná automaticky, když je vytvářen objekt dané třídy. Provádí inicializaci (počáteční nastavení) objektu. Má stejné jméno jako třída, jejíž je součástí a nemá návratový typ. Třída může mít více konstruktorů, z nichž každý obsahuje jiný seznam parametrů (jde o přetížené metody). Seznam parametrů se obvykle používá s konstruktorem pro inicializaci atributů třídy. Pokud nevytvoříme vlastní konstruktor, je použit tak zvaný implicitní konstruktor, jako programech Program 1 a Program 3, který nemá parametry. Program 5 Vytvoření konstruktoru pro nastavení hodnoty soukromé proměnné ve třídě V programu Program 3 je pro vytvoření objektuTC použit implicitní konstruktor. Zde si ukážeme použití vlastního konstruktoru: public TridaCislo (int b), který
nastavuje hodnotu privátní proměnné Cislo na hodnotu parametru konstruktoru. using System; class TridaCislo { /*Položka Cislo je soukromá.*/ int Cislo=1; static void Main() { TridaCislo TC = new TridaCislo (123); Console.WriteLine("{0}", TC.Cislo); Console.ReadLine(); } public TridaCislo (int b) { Cislo = b; } }
Konstruktor je volán při vytváření objektu TC. C# nedisponuje destruktory v takovém smyslu jako například C++. 2.11.11
Základy objektově orientovaného programování (OOP)
14/41
V C++ byl destruktor doplňkem konstruktoru a byl volaný při rušení objektu – při rušení se prováděly určité akce (např. uvolnění paměti). V jazyce C# se jako destruktory označují konstrukce, označované v jiných jazycích jako finalizátory. Volají se v okamžiku, kdy je objekt odstraňován z paměti. Programátor nemá přímou možnost ovlivnit okamžik, kdy bude destruktor zavolán, a proto také destruktory v C# nejsou tak užitečné jako v C++. Konstruktor nemá návratovou hodnotu. Parametrizované konstruktory Jak již bylo uvedeno, konstruktor může mít parametry. Parametrizované metody můžeme přetížit – tj. definovat více stejnojmenných metod, lišících se parametry. Konstruktor může mít parametry a může být přetížený – tzn. můžeme vytvořit více konstruktorů, lišících se počtem, nebo typem parametrů, nebo obojím. Jestliže nevytvoříme žádný konstruktor, kompilátor vytvoří implicitní. Pokud definujeme vlastní konstruktor, negeneruje překladač implicitní metodu. Parametrizovaný konstruktor se často používá pro nastavení hodnot soukromých atributů objektu na hodnoty parametrů konstruktoru. Parametrů může být více. Parametry se v konstruktorech definují stejně jako v případě metod - stačí je uvést uvnitř kulatých závorek za jménem konstruktoru. Použití přetíženého konstruktoru ilustruje Program 16. Program 6 Spolupráce dvou tříd V dosud uvedených příkladech byla použita jedna třída, jejíž součástí byl Main. V následujícím programu je vytvořená třída Zarovka, obsahující privátní datovou položku a, která indikuje, zda žárovka svítí, nebo nesvítí. Metoda Main je uvedena v jiné třídě, nazvané Hlavni Třída Zarovka obsahuje veřejné metody pro rozsvícení, zhasnutí a zobrazení stavu žárovky. V Mainu je vytvořen objekt lt třídy Zarovka , na který jsou použity metody pro její rozsvícení, zhasnutí a zobrazení stavu. using System; class Zarovka { bool a; public void Rozsvit(){a=true;} public void Zhasni() { a = false; } public void Zobraz() { if (a) Console.WriteLine("Sviti"); else Console.WriteLine("Nesviti"); } }; class Hlavni 2.11.11
Základy objektově orientovaného programování (OOP)
15/41
{ public static void Main(){ Zarovka lt=new Zarovka(); lt.Rozsvit(); lt.Zobraz(); lt.Zhasni(); lt.Zobraz(); Console.ReadLine(); } // konec Main } // konec Hlavni
Znázornění třídy diagramem UML Zarovka
- bool a + Rozsvit() + Zhasni() +Zobraz()
Obrázek 4 Znázornění třídy Zarovka diagramem UML
Vytvoření pole objektů Stejným způsobem, jakým vytváříme pole proměnných základních datových typů, můžeme vytvářet pole objektů. Vytvoření pole objektů: Třída[] NázevPole=new Třída[počet]; S prvky pole můžeme pracovat pomocí cyklů nejčastěji for, nebo foreach – viz. následující příklad. Program 7 Práce s polem objektů Vytvořte pole deseti žárovek a střídavě je rozsviťte a zhasněte! Pro práci s polem objektů je použita třída Zarovka z programu Program 6. using System; class Zarovka{ bool a; public void Rozsvit(){a=true;} public void Zhasni(){a=false;} public void Zobraz() { 2.11.11
Základy objektově orientovaného programování (OOP)
16/41
if (a) Console.Write("+ "); else Console.Write(". "); } } class Program{ static void Main() { Zarovka[] Z=new Zarovka [10]; // pole objektů žárovka for (int i = 0,j=1; j < 10;i=i+2,j=j+2 ) { Z[i]=new Zarovka(); Z[j]=new Zarovka(); Z[i].Rozsvit(); Z[j].Zhasni(); } foreach ( Zarovka Z1 in Z) { Z1.Zobraz(); // zobraz. hodnot privát. prom. objektů } Console.ReadLine(); } }
V programu je vidět použití cyklu foreach na všechny objekty pole Z.
Přiřazování objektů Jsou – li dva objekty stejné třídy, může být jeden objekt přiřazen druhému: Třída O1=new Třída(); Třída O2=new Třída(); O2 = O1;
Přiřazením dojde k tomu, že všechny položky objektu na levé straně příkazu přiřazení nabudou hodnoty odpovídajících položek objektu na pravé straně příkazu přiřazení. Příkaz přiřazení můžeme použít i pro celé pole, jak ilustruje následující příklad:
Program 8 Přiřazování objektů using System; class Zarovka{ bool a; public void Rosvit(){a=true;} public void Zhasni(){a=false;} public void Zobraz() { if (a) Console.Write("+ "); else Console.Write(". ");
2.11.11
Základy objektově orientovaného programování (OOP)
17/41
} } class Program{ static void Main() { Zarovka[] Z=new Zarovka [10]; // pole objektů žárovka Zarovka[] ZZ = new Zarovka[10]; // pole objektů žárovka for (int i = 0,j=1; j < 10;i=i+2,j=j+2 ) { Z[i]=new Zarovka(); Z[j]=new Zarovka(); Z[i].Rosvit(); Z[j].Zhasni(); } ZZ = Z; foreach ( Zarovka Z1 in ZZ) { Z1.Zobraz(); // zobraz. hodnot privát. prom. objektů } Console.ReadLine(); } }
Příkazem: ZZ = Z; všechny prvky pole Z přiřadíme do odpovídajících prvků pole ZZ.
Třídní data a třídní metody Třídní data a třídní metody definujeme za klíčovým slovem static. Třídní data jsou umístěna na jednom místě v paměti počítače, jsou stejná a dostupná ve všech objektech dané třídy. To lze využít například při počítání vytvořených objektů. Program 9 Počítadlo vytvořených objektů Do třídy Zarovka v programu Program 7 je doplněna statická proměnná počet, která bude uchovávat počet vytvořených objektů třídy Zarovka. Vlastní počítání sektů je zajištěno v konstruktoru – při každém volání konstruktoru se hodnota počítadla inkrementuje. using System; class Zarovka{ bool a; static int pocet; void Rosvit() { a = true; } void Zhasni() { a = false; } Zarovka() { pocet++; } // Konstruktor void Zobraz() { 2.11.11
Základy objektově orientovaného programování (OOP)
18/41
if (a) Console.Write("+ "); else Console.Write(". "); } static void ZobrazPocet() { Console.Write("Pocet objektu je: {0}\n", pocet); } static void Main() { Zarovka[] ZP = new Zarovka[10]; // pole objektů žárovka for (int i = 0, j = 1; j < 10; i = i + 2, j = j + 2) { ZP[i] = new Zarovka(); ZP[i].Rosvit(); ZP[j] = new Zarovka(); ZP[j].Zhasni(); } foreach (Zarovka zar in ZP) zar.Zobraz(); Console.WriteLine("\n"); Zarovka Z = new Zarovka(); Zarovka ZZ = new Zarovka(); Zarovka.ZobrazPocet(); Console.ReadLine(); } }
Program vypíše: +.+.+.+.+. Pocet objektu je: 12
Předávání objektů metodám přes parametry Objekt může být parametrem metody, jak ilustruje následující příklad. Program 10 Objekt jako parametr metody Následující příklad ilustruje skutečnost, že jeden objekt má přístup k soukromým datům jiného objektu téže třídy Program obsahuje dvě třídy: student a Program. Třída Program obsahuje Main. Třída student obsahuje: soukromou datovou položku vek, do níž se pomocí konstruktoru uloží věk studenta konstruktor pro nastavení věku parametrizovanou metodu vypis pro výpis věku studenta, který je metodě předán jako parametr neparametrizovanou metodu vypis pro výpis věku studenta, který je volajícím objektem metody 2.11.11
Základy objektově orientovaného programování (OOP)
19/41
V Mainu je nejprve pomocí objektu Petr volaná parametrizovaná metoda vypis s parametrem Pavel – vypíše se Pavlův věk, a potom je pomocí objektu Petr volaná neparametrizovaná metoda vypis - vypíše se Petrův věk. using System; class student { int vek; public student(int v) { vek = v; } public void vypis(student S) { Console.WriteLine("vek: {0}", S.vek); } public void vypis() { Console.WriteLine("vek: {0}", this.vek); } } class Program { static void Main() { student Petr = new student(16); student Pavel = new student(17); Petr.vypis(Pavel); Petr.vypis(); Console.ReadLine(); } }
Pomocí Petra mohu vypsat Pavlův věk a naopak. V případě uvedeného programu Program 10 by bylo lepší použít statickou metodu vypis, kterou budeme volat pomocí názvu třídy student. Statické metody se volají pomocí názvu třídy a operátoru tečka. Program 11 Použití statické metody using System; class student { int vek; public student(int v){vek=v;} public static void vypis(student S) { Console.WriteLine("vek: {0}", S.vek); } } class Program{ static void Main() { student Petr = new student(16); student Pavel=new student(17); student.vypis(Pavel); student.vypis(Petr); Console.ReadLine(); } } 2.11.11
Základy objektově orientovaného programování (OOP)
20/41
Vracení objektů metodami Metodu deklarujeme s návratovou hodnotou třída public static Třída Metoda(parametry) { … return ObjektTřídy; }
Program 12 Metoda, která vrací objekt Třída Řetězec obsahuje privátní atribut s a veřejné metody Zobraz a Nastav . Třída VraciObjekt obsahuje metodu Vstup , která vrací objekt třídy Řetězec . using System; public class Řetězec { string s; public void Zobraz() { Console.WriteLine(s); } public void Nastav(string str) { s = str; } } public class VraciObjekt { // Vracet objekt dané třídy nemusí jen metody třídy. // Metoda vstup není členskou funkcí Řetězec, // ale vrací objekt třídy Řetězec. public static Řetězec Vstup() { string s; // Vytvoření objektu třídy Řetězec Řetězec str = new Řetězec(); Console.Write("Zadej řetězec: "); s = Console.ReadLine(); str.Nastav(s); // Nastavení hodnoty objektu třídy Řetězec return str; // Vrácení hodnoty objektu třídy Řetězec } public static void Main() { Řetězec ret=new Řetězec(); ret = Vstup(); // Nastavení řetězce ret.Zobraz(); // Zobrazení řetězce Console.ReadLine(); } }
Metody, které vrací objekt jsou použity i v programech Program 12 a Program 17.
this – odkaz na aktuální instanci Klíčové slovo this se vztahuje k aktuálnímu objektu - je to odkaz na objekt, vytvářející volání: ob.m1(); 2.11.11
Základy objektově orientovaného programování (OOP)
21/41
Ukazatel this je metodě předán jako skrytý parametr. Tento ukazatel má každá členská funkce včetně konstruktorů. V těle nestatické metody musí program znát instanci, pro kterou je volána – jinak by nedokázal určit položky, se kterými má pracovat. Ve statických metodách není toto klíčové slovo k dispozici. Program 13 Použití this V uvedeném programu je použitý operátor this pro vrácení věku mladšího studenta. using System; class student { int vek; public student(int v){vek=v;} public static void vypis(student S) { Console.WriteLine("vek: {0}", S.vek); } public student mladsi(student s){ if(s.vek
Kompozice Opětné použití implementace - skládání Novou třídu lze sestavit z libovolného počtu a typů jiných objektů. Používá se vazba „obsahuje“ nebo „má“
AUTO
MOTOR Obrázek 5 Příklad kompozice
2.11.11
Základy objektově orientovaného programování (OOP)
22/41
Skládání je jednodušší a pružnější než dědičnost. Program 14 Ilustrace kompozice
Y
X Obrázek 6 Kompozice tříd - ilustrace programu
using System; class X { int i; public X() { i = 0; } public void nastav_i(int ii) { i = ii; } public int vrat_i() { return i; } }; //Třída Y obsahuje objekt třídy X class Y { int i; public X x = new X(); //Vnořený objekt ve veřejné části public Y() { i = 0; } // konstruktor public void nastav_i(int ii) { i = ii; } public int vrat_i() { return i; } }; class Program { static void Main() { Y y = new Y();// vytvoření objektu třídy Y y.nastav_i(20); // volání metody třídy Y Console.WriteLine("{0}", y.vrat_i()); // Přístup ke vnořenému objektu: // vnější.vnitřní.metoda() y.x.nastav_i(10); // volání metod třídy X Console.WriteLine("{0}", y.x.vrat_i()); Console.ReadLine(); } }
Zde je nutné k nastavení a vrácení hodnoty privátních proměnných i použít metody nastav_i a vrat_i(), které jsou veřejné (public). Nebylo by možné použít: z.i, nebo z.x.i. To by bylo možné pouze tehdy, kdyby proměnná i byla veřejná (public), jak je v následujícím programu: using System;
2.11.11
Základy objektově orientovaného programování (OOP)
23/41
class X { public public }; class Y { public public public };
int i; X() { i = 0; }
int i; X x = new X(); //Vnořený objekt ve veřejné části Y() { i = 0; } // konstruktor
class Program { static void Main() { Y y = new Y(); y.i = 100; Console.WriteLine("{0}", y.i); y.x.i = 200; Console.WriteLine("{0}", y.x.i); Console.ReadLine(); } }
Zde je možné nastavovat veřejnou proměnnou i přímo, bez použití přístupových metod.
Celou třídu X mohu definovat uvnitř třídy Y: using System; class Y { public class X { int i; public X() { i = 0; } public void nastav_i(int ii) { i = ii; } public int vrat_i() { return i; } }; int i; public X x = new X(); //Vnořený objekt ve veřejné části public Y() { i = 0; } // konstruktor public void nastav_i(int ii) { i = ii; } public int vrat_i() { return i; } }; class Program { static void Main() { Y y = new Y(); y.nastav_i(20); // volání metod třídy Y Console.WriteLine("{0}", y.vrat_i()); // Přístup ke vnořenému objektu: // vnější.vnitřní.metoda() 2.11.11
Základy objektově orientovaného programování (OOP)
24/41
y.x.nastav_i(10); // volání metod třídy X Console.WriteLine("{0}", y.x.vrat_i()); Console.ReadLine(); } }
Vlastnosti Vlastnosti se uživateli jeví jako proměnné, ale zjišťování aktuální hodnoty a nastavení nových hodnot probíhá prostřednictvím metod. Dá se říct, že vlastnost je inteligentní proměnná – proměnná ví, jakých hodnot může nabýt. Inteligenci do ní vložil programátor definováním přístupových metod. Přístupové metody Vlastnost se skládá z deklarace vlastnosti a jednoho, nebo dvou programových bloků, označovaných jako přístupové metody, které zprostředkovávají přečtení, nebo nastavení hodnoty vlastnosti. Vlastnosti mohou definovat: samotnou čtecí metodu – vlastnost je pouze pro čtení samotnou nastavovací metodu – je pouze pro zápis obě metody – je pro čtení i zápis Následující příklad ilustruje vytvoření vlastnosti Znamka, jejíž přístupová metoda set kontroluje rozsah zadané známky. Program 15 Definování vlastnosti pro zadávání známek a její použití using System; class VlastnostZnamka { protected int z; public int Znamka { Get // čtecí metoda { return z; } Set // nastavovací metoda { if(value == 0)Console.WriteLine("Konec"); else if ((value < 6) & (value > 0)) z = value; else Console.WriteLine("Chyba"); } } }; 2.11.11
Základy objektově orientovaného programování (OOP)
25/41
class M { static void Main() { VlastnostZnamka zn = new VlastnostZnamka(); double s = 0, pocet = 0; int vstup; do{ vstup=Int32.Parse(Console.ReadLine()); zn.Znamka = vstup; s += zn.Znamka; pocet++; }while(vstup!=0); Console.WriteLine("{0:F2}", s / pocet); Console.ReadLine(); } }
Program vypíše průměr správně zadaných známek. Běh programu: 7 Chyba 8 Chyba 1 2 3 0 Konec 1,50
Vlastnosti se hodí pro situace, kdy při zavolání nastavovací funkce chceme kromě pouhého nastavení hodnoty provést ještě nějaké další činnosti. Zde po načtení známky chceme zkontrolovat, zda známka je v požadovaném rozsahu.
2.11.11
Základy objektově orientovaného programování (OOP)
26/41
Otázky z probrané látky 1. Jak dělíme programovací jazyky? 2. Jaký je rozdíl mezi procedurálnímí a objektově orientovanými jazyky? 3. Proč je pro programátory důležité využívat OOP k vývoji aplikací? 4. Vysvětlete základní principy OOP! 5. Co je základní jednotkou zapouzdření v objektově orientovaném jazyce? 6. Co je to třída? 7. Co je to objekt? 8. Vysvětlete rozdíl mezi třídou a objektem! 9. Vysvětlete pojem abstrakce v reprezentaci dat! 10. Co víte o UML? 11. Co je to zapouzdření? 12. Co je to skrývání informací a implementací? 13. Co je to zachování stavu? 14. Co je to identita objektu? 15. Co je to zpráva, argumenty zpráv, typy zpráv a jaká je role objektů ve zprávách? 16. Jaké jsou prostředky pro OOP v C#? 17. Co je to specifikátor přístupu? 18. Co je to specifikátor veřejného přístupu? 19. Co je to specifikátor privátního přístupu? 20. Co je to specifikátor chráněného přístupu? 21. Proč programátoři vyžadují, aby se k některým atributům třídy dalo přistupovat pouze prostřednictvím členské funkce neboli metody? 22. Co je to konstruktor a destruktor, jak je definujeme a jakou činnost provádí? 23. Jak lze vytvořit nový objekt dané třídy? 24. Jak lze deklarovat pole objektů? 25. Kdy je možné přiřadit jeden objekt druhému, jak to zapíšeme a co nastane? 26. Co jsou třídní data a třídní metody? 27. Jak lze objekty předávat funkcím jako parametry? 28. Jak definujeme metodu, která bude vracet jako návratovou hodnotu objekt? 29. Co víte o ukazateli this? 30. Co je to kompozice? 31. Co jsou vlastnosti? 32. Co mohou vlastnosti definovat? 33. Jak definujeme čtecí metodu vlastnosti? 34. Jak definujeme nastavovací metodu vlastnosti?
2.11.11
Základy objektově orientovaného programování (OOP)
27/41
Příklady Program 16 Příklad přetíženého konstruktoru using System; class MojePrvniTrida { /* Třída obsahuje dvě soukromé proměnné: Cislo a Znak */ private int Cislo; char Znak; static void Main() { int a = 1; /* Použití bezparametrického konstruktoru */ MojePrvniTrida MPT = new MojePrvniTrida(); Console.WriteLine("Cislo = {0}", MPT.Cislo); /* Použití konstruktoru se znakovým parametrem*/ MojePrvniTrida MP = new MojePrvniTrida('#'); /* Použití konstruktoru se dvěma parametry */ MojePrvniTrida M = new MojePrvniTrida(1919, '@'); Console.ReadLine(); } /* Bezparametrický konstruktor */ public MojePrvniTrida() { Cislo = 0; } /* Konstruktor s celočíselným parametrem*/ public MojePrvniTrida(int b) { Cislo = b; } /* Konstruktor se znakovým parametrem */ public MojePrvniTrida(char z) { Znak = z; Console.WriteLine("Znak = " + Znak); } /* Konstruktor se dvěma parametry: celočíselným a znakovým */ public MojePrvniTrida(int b, char z) { Cislo = b; Znak = z; Console.WriteLine("Cislo = {0}\nZnak = {1}", Cislo, Znak); } }
Vypíše se: Cislo = 0 Znak = # Cislo = 1919 Znak = @
Třída MojePrvniTrida obsahuje 4 konstruktory se stejným jménem jako třída: MojePrvniTrida, lišící se typem a počtem parametrů (jsou to přetížené metody): 2.11.11
Základy objektově orientovaného programování (OOP)
28/41
První nemá žádné parametry a v Mainu je použit k vytvoření objektu MPT Druhý má 1 parametr typu int a v Mainu není použitý Třetí má 1 parametr typu char a v Mainu je použit k vytvoření objektu MP Čtvrtý má 2 parametry typu int a char a v Mainu je použit k vytvoření objektu M
Program 17 Hledání nejlepšího studenta using System; class Student { string jmeno; double prum; public Student(string jm, double pr) { jmeno = jm; prum = pr; } static public Student Lepsi(Student S1, Student S2) { return (S1.prum < S2.prum) ? S1 : S2; } public string VratJmeno() { return jmeno; } public double VratPrumer() { return prum; } } class M { static void Main() { Student[] V2 = new Student[]{ new Student("Josef",1.5), new Student("Jan",1.2), new Student("Petr",2.5), new Student("Pavel",2.1), new Student("Eva",1.9), new Student("Zuzana",1.95), new Student("Adam",2.45), new Student("Filip",2.75), new Student("Kateřina",3.5), }; Student Nej = new Student("aaa", 5); foreach (Student s in V2) { Nej = Student.Lepsi(Nej, s); } Console.WriteLine("Nejlepší je {0} a má průměr: {1}", Nej.VratJmeno(),Nej.VratPrumer()); Console.ReadLine(); } 2.11.11
Základy objektově orientovaného programování (OOP)
29/41
}
Popis programu: Program obsahuje dvě třídy: Student a M, obsahující Main. Třída Student má: privátní datové položky jmeno a prum veřejné metody: konstruktor Student, VratJmeno, Vratprumer a statickou metodu Lepsi, která vrací lepšího ze dvou studentů, které převezme jako parametry. V Mainu je vytvořeno pole studentů a student Nej, kterému je konstruktorem zadáno jméno aaa a nemožný průměr 5. Dále je v cyklu foreach procházeno pole studentů a hledán nejlepší student. Za cyklem je vypsáno jméno a průměr tohoto studenta s využitím funkcí: VratJmeno() a VratPrumer(). Program 18 Definování vlastností Modifikace uvedeného programu: Následující program je modifikací výše uvedeného programu Program 17 s tím, že namísto metod: VratJmeno() a VratPrumer() jsou definovány vlastnosti JMENO a PRUMER. Definice vlastnosti PRUMER obsahuje kontrolu možného rozsahu průměru, stejně jako konstruktor třídy Student. using System; class Student { string jmeno; double prum; public Student(string jm, double pr) { jmeno = jm; if ((pr < 5) && (pr > 0)) prum = pr; else Console.WriteLine("Chyba"); } static public Student Lepsi(Student S1, Student S2) { return (S1.prum < S2.prum) ? S1 : S2; } public string JMENO { get { return jmeno; } set { jmeno=value; 2.11.11
Základy objektově orientovaného programování (OOP)
30/41
} } public double PRUMER { get { return prum; } set { if ((value < 5) & (value > 0)) prum = value; else Console.WriteLine("Chyba"); } } } class M { static void Main() { Student[] V2 = new Student[]{ new Student("Josef",1.5), new Student("Jan",1.2), new Student("Petr",2.5), new Student("Pavel",2.1), new Student("Eva",1.9), new Student("Zuzana",1.95), new Student("Adam",2.45), new Student("Filip",2.75), new Student("Kateřina",3.5), }; Student Nej = new Student("aaa", 4.9); foreach (Student s in V2) { Nej = Student.Lepsi(Nej, s); } Console.WriteLine("Nejlepší je {0} a má průměr: {1}", Nej.JMENO,Nej.PRUMER); Console.ReadLine(); } }
Program 19 Třída s přetíženým konstruktorem a destruktorem Následující program ilustruje použití přetíženého konstruktoru a destruktoru. Destruktor je metoda, která má stejné jméno jako třída, do které patří předcházené znakem ~. using System; public class VypisTextu { public string oblibenyProgram; public static int pocetObjektu; public VypisTextu() 2.11.11
Základy objektově orientovaného programování (OOP)
31/41
{ Console.WriteLine("Konstruktor VypisTextuu"); pocetObjektu++; oblibenyProgram = "C#"; } public VypisTextu(string param1) { Console.WriteLine("Přetížený konstruktor VypisTextu"); pocetObjektu++; oblibenyProgram = param1; } ~VypisTextu() { Console.WriteLine("Destruktor VypisTextu"); } static public int KolikObjektu() { return pocetObjektu; } public void Zobraz() { Console.WriteLine("Mám ráda " + oblibenyProgram); } } public class M { public static void Main(string[] args) { VypisTextu[] x = new VypisTextu[10]; x[0] = new VypisTextu(); x[0].oblibenyProgram = "C#"; x[0].Zobraz(); x[1] = new VypisTextu(); x[1].oblibenyProgram = "Visual Basic"; x[1].Zobraz(); for (int i = 0; i < VypisTextu.KolikObjektu(); i++) { Console.WriteLine(x[i].oblibenyProgram); } } }
Program obsahuje dvě třídy VypisTextu a M s Mainem. Třída VypisTextu obsahuje dvě veřejné datové položky: oblibenyProgram a pocetObjektu. Protože jsou veřejné, je k nim možné přímo přistupovat z Mainu bez přístupových metod a definovaných vlastností. 2.11.11
Základy objektově orientovaného programování (OOP)
32/41
Třída VypisTextu má definované dva konstruktory: parametrizovaný a neparametrizovaný. Parametrizovaný konstruktor přebírá text, kterým nastavuje hodnotu datové položky oblibenyProgram a neparametrizovaný nastavuje tuto položku na hodnotu C#. Oba konstruktory inkrementují hodnotu položky pocetObjektu. Třída VypisTextu dále obsahuje metodu KolikObjektu, která vrací počet vytvořených objektů a metodu Zobraz, která vypíše hodnotu datové položky oblibenyProgram pro určitý objekt. V Mainu je vytvořeno pole objektů třídy VypisTextu a jsou nastaveny hodnoty položky oblibenyProgram pro každý vytvořený objekt. Nastavená hodnota je následně zobrazena metodou Zobraz . Program 20 Objektově orientovaná kalkulačka using System; class Kalk{ Kalk char c; double a; double b; - char c public double vypocet() - double a { switch (c) - double b { case '+': return (a + b); case '-': return (a - b); + vypocet() case '*': return (a * b); + zadani() case '/': return (a / b); default: return 0; } } Obrázek 7 UML digram třídy Kalk public bool zadani() { Console.WriteLine("Zadej 2 cisla:"); a = double.Parse(Console.ReadLine()); if (a == 0) return false; b = double.Parse(Console.ReadLine()); Console.WriteLine("Zadej operaci:"); c = Convert.ToChar(Console.ReadLine()); return (c == '+') | (c == '-') | (c == '*') | (c == '/'); } } class Program { static void Main() { Kalk o = new Kalk(); do { if (!o.zadani()) break; Console.WriteLine("{0}", o.vypocet());
2.11.11
Základy objektově orientovaného programování (OOP)
33/41
} while (true); } }
V uvedeném programu jsou 2 třídy: Kalk a Program. Funkce Kalk má tři privátní proměnné pro uchování hodnot dvou operandů a operátoru a dvě metody: zadani a vypocet. Metoda zadání načte hodnoty do privátních proměnných a metoda vypocet vypočítá hodnotu zadaného výrazu a vrátí ji do volající jednotky. Funkce Main je ve třídě Program volá metody zadani() a vypocet() musí být proto veřejné (public). Program se ukončí zadáním operátoru různého od ‘+’, ‘-’, ‘*’, ‘/’, nebo zadáním nulové hodnoty některého operandu. Program 21 Ukázka kompozice tříd Obdelnik a Bod using System; class Bod { int x; int y; public Bod(int i, int j) { x = i; y = j; } public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } }; class Obdelnik { Bod lh, pd; ConsoleColor b; public Obdelnik(Bod lh, Bod pd, ConsoleColor b) { this.lh = lh; this.pd = pd; this.b = b; } public Bod LH { get { return lh; } set { this.LH = value; } } public Bod PD { get { return pd; } set { this.PD = value; } }
2.11.11
Základy objektově orientovaného programování (OOP)
34/41
public ConsoleColor Barva { get { return b; } set { this.b = value; } } } class Program { static void Main() { Bod lh = new Bod(5, 5); Bod pd = new Bod(30, 10); Obdelnik o = new Obdelnik(lh, pd, ConsoleColor.Green); Console.ForegroundColor = o.Barva; for (int y = o.LH.Y; y < o.PD.Y; y++) for (int x = o.LH.X; x < o.PD.X; x++) { Console.SetCursorPosition(x, y); Console.Write("█"); } Console.ReadLine(); } }
V uvedeném programu jsou 2 třídy: Obdelnik a Bod. Třída Obdelnik pracuje s dvěma objekty třídy Bod lh(levý horní roh obdélníku) a pd(pravý dolní roh obdélníku). Ve třídě Bod jsou definovány vlastnosti X, Y a ve třídě Obdelnik LH a PD. Obě třídy mají definované konstruktory. Konstruktor třídy Bod nastavuje souřadnice bodu v pořadí x, y. Konstruktor třídy Obdelnik nastavuje levý hornbí a pravý dolní roh obdélníku a jeho barvu.. V Mainu jsou vytvořeny dva objekty třídy Bod (lh apd), které jsou předány jako parametry konstruktoru třídy Obdelnik spolu s požadovanou barvou a obdélník je vykreslený pomocí dvou cyklů for a znaku "█" . Program 22 Pohyb robota po zadané cestě Pro následující program jsou definovány tři třídy: Mrizka, Robot, Program. Třída Mrizka umožňuje zadat cestu robota na obrazovce v mřížce 80x40. Obsahuje následující metody: public void UlozMrizku() pro uložení mřížky public void ObnovMrizku() pro obnovení mřížky
a dvě statická dvojrozměrná pole: static public bool[,] mriz = new bool[80, 40]; static public bool[,] mrizka = new bool[80, 40];
Třída Robot zajišťuje pohyb robota v mřížce. Obsahuje následující metody: public void Ini() nastaví robota do výchozí pozice public void otocitVlevo() otočit robota vlevo 2.11.11
Základy objektově orientovaného programování (OOP)
35/41
public void otocitVpravo()otočit robota vpravo public void krok() krok robota ve směru natočení public bool zed() test, zda robot má před sebou zeď public void zobraz() zobrazení robota se zpožděním public void UlozCestu(ref int kroky) uživatel nakreslí cestu robota a uloží ji do mřížky
Třída Program obsahuje metodu Main, v níž vytvoříme object M třídy Mrizka a object R třídy Robot . Po spuštění programu nejprve uživatel nakreslí cestu robota pomocí kurzorových kláves. Kreslení cesty se ukončí klávesou Escape.
Obrázek 8 Nakreslená cesta robota
Obrázek 9 Pohyb robota po cestě
Potom v cyklu while robot opakovaně prochází touto cestou, dokud není jeho pohyb přerušen stisknutím libovolné klávesy (podmínka !Console.KeyAvailable). using System; using System.Threading; using System.Collections.Generic; using System.Linq; using System.Text; class Mrizka { static public bool[,] mriz = new bool[80, 40]; static public bool[,] mrizka = new bool[80, 40]; public void UlozMrizku() { for (int i = 0; i < 80; i++) for (int j = 0; j < 40; j++) mriz[i, j] = mrizka[i, j]; 2.11.11
Základy objektově orientovaného programování (OOP)
36/41
} public void ObnovMrizku() { for (int i = 0; i < 80; i++) for (int j = 0; j < 40; j++) mrizka[i, j] = mriz[i, j]; } } class Robot { public int x = 0, y = 0; public char rob; // Hominoid mrizka - umoznuje zadat mrizku Hominoidu // pomoci stopy kurzorovych sipek public void Ini() { rob = '>'; x = 0; y = 0; Console.SetCursorPosition(x, y); Console.Write(rob); } public void otocitVlevo() { switch (rob) { case '>': rob = '^'; break; case '^': rob = '<'; break; case '<': rob = 'v'; break; case 'v': rob = '>'; break; } } public void otocitVpravo() { switch (rob) { case '>': rob = 'v'; break; case '^': rob = '>'; break; case '<': rob = '^'; break; case 'v': rob = '<'; break; } } public void krok() { switch (rob) { case '>': if (x > 78) return; else x++; break; case '^': if (y > 0) y--; break; case '<': if (x > 0) x--; break; case 'v': if (y > 38) return; else y++; break; } Thread.Sleep(10); Mrizka.mrizka[x, y] = false; } public bool zed() { 2.11.11
Základy objektově orientovaného programování (OOP)
37/41
switch (rob) { case '>': if (Mrizka.mrizka[x + 1, y] == true) return false; else break; case '^': if (y > 0) { if (Mrizka.mrizka[x, y - 1] == true)return false; else break; }else break; case '<': if (x > 0) { if (Mrizka.mrizka[x - 1, y] == true)return false; else break; } else break; case 'v': if (Mrizka.mrizka[x, y + 1] == true) return false; else break; default: break; } return true; } public void zobraz() { Console.SetCursorPosition(x, y); Console.Write(rob); Thread.Sleep(100); } public void UlozCestu(ref int kroky) { ConsoleKeyInfo cki; Console.Clear(); Console.SetCursorPosition(0, 0); Console.Write("#"); do { cki = Console.ReadKey(false); switch (cki.Key) { case ConsoleKey.LeftArrow: if (x > 0) x--; break; case ConsoleKey.RightArrow: if (x < 79) x++; break; case ConsoleKey.UpArrow: if (y > 0) y--; break; case ConsoleKey.DownArrow: if (y < 39) y++; break; case ConsoleKey.Delete: Console.Clear(); break; default: break; }; Console.SetCursorPosition(x, y); Console.WriteLine("#"); Mrizka.mrizka[x, y] = true; kroky++; } while (cki.Key != ConsoleKey.Escape); // konec cyklu } }; class Program { static void Main() { int kroky = 0; Mrizka M=new Mrizka(); Robot R = new Robot(); R.UlozCestu(ref kroky); Console.Clear(); M.UlozMrizku(); Console.Clear(); while (!Console.KeyAvailable) { R.Ini(); 2.11.11
Základy objektově orientovaného programování (OOP)
38/41
for (int k = 0; k < kroky; k++) { { if (!R.zed()) { R.krok(); R.zobraz(); } else { R.otocitVpravo(); R.zobraz(); } if (Console.KeyAvailable) break; } } Console.Clear(); M.ObnovMrizku(); } } }
Program 23 Výpočet průměru studentů - data jsou v souboru /*Data jsou v souboru studenti.txt Petr 1 1 1 2 2 Pavel 2 2 2 3 3 Jan 3 3 3 4 4 */ // Výpočet průměru metodou průměr using System; using System.IO; class student { public string jmeno; public int[] znamky = new int[5]; public double prum; public void prumer (){ double p = 0; for (int i = 0; i < 5;i++ ) { p += znamky[i]; } prum= p/5.0; } } class Program { static void Main() { string[] jmena = new string[30]; student[] s = new student[30]; StreamReader sr = new StreamReader(@"..\..\studenti.txt"); string ret = sr.ReadToEnd(); char[] oddel = new char[] { '\n' };
2.11.11
Základy objektově orientovaného programování (OOP)
39/41
char[] odd = new char[] { ' ' }; string[] radek = new string[30]; radek = ret.Split(oddel); string[] rad = new string[7]; for (int i = 0; i < radek.Length; i++) { rad = radek[i].Split(odd); s[i] = new student(); s[i].jmeno = rad[0]; for (int j = 1; j < 6; j++) s[i].znamky[j - 1] = Convert.ToInt32(rad[j]); s[i].prumer(); } for (int i = 0; i < radek.Length; i++) { Console.Write(s[i].jmeno + "\t"); for (int j = 0; j < 5; j++) Console.Write(" " + s[i].znamky[j]); Console.Write("\t"+s[i].prum); Console.WriteLine(); } } }
Spustitelné kódy všech uvedených programů jsou v souboru EXE.ZIP. Seznam programů Program 1 Třída pro uchování celého čísla .................................................................................................... 12 Program 2 Použití statické proměnné ve stejné třídě jako Main ................................................................ 13 Program 3 Použití nestatické proměnné ........................................................................................................ 13 Program 4 Použití statické proměnné Cislo .......................................................................................................... 13 Program 5 Vytvoření konstruktoru pro nastavení hodnoty soukromé proměnné ve třídě ................... 14 Program 6 Spolupráce dvou tříd..................................................................................................................... 15 Program 7 Práce s polem objektů ..................................................................................................................... 16 Program 8 Přiřazování objektů ........................................................................................................................ 17 Program 9 Počítadlo vytvořených objektů ..................................................................................................... 18 Program 10 Objekt jako parametr metody..................................................................................................... 19 Program 11 Použití statické metody ............................................................................................................... 20 Program 12 Metoda, která vrací objekt ........................................................................................................... 21 Program 13 Použití this .................................................................................................................................... 22 Program 14 Ilustrace kompozice ..................................................................................................................... 23 Program 15 Definování vlastnosti pro zadávání známek a její použití ..................................................... 25 Program 16 Příklad přetíženého konstruktoru ............................................................................................. 28 Program 17 Hledání nejlepšího studenta ....................................................................................................... 29 Program 18 Definování vlastností................................................................................................................... 30 Program 19 Třída s přetíženým konstruktorem a destruktorem................................................................ 31 Program 20 Objektově orientovaná kalkulačka ............................................................................................ 33 Program 21 Ukázka kompozice tříd Obdelnik a Bod................................................................................... 34 Program 22 Pohyb robota po zadané cestě ..................................................................................................... 35
2.11.11
Základy objektově orientovaného programování (OOP)
40/41
Program 23 Výpočet průměru studentů - data jsou v souboru .................................................................. 39
Seznam obrázků Obrázek 1 Ilustrace objektů, atributů a metod ........................................................................................................ 4 Obrázek 2 Diagram UML, znázorňující třídu ......................................................................................................... 6 Obrázek 3 Předání zprávy objektu .......................................................................................................................... 9 Obrázek 4 Znázornění třídy Zarovka diagramem UML ........................................................................................ 16 Obrázek 5 Příklad kompozice ............................................................................................................................... 22 Obrázek 6 Kompozice tříd - ilustrace programu ................................................................................................... 23 Obrázek 7 UML digram třídy Kalk ....................................................................................................................... 33 Obrázek 8 Nakreslená cesta robota ....................................................................................................................... 36 Obrázek 9 Pohyb robota po cestě .......................................................................................................................... 36
Literatura [1] James Keogh, Mario Giannini: OOP objektově orientované programování bez předchozích znalostí, Computer Press, 2006 [2] Dalibor Kačmář: Programujeme .NET aplikace ve Visual Studiu .NET, Computer Press, 2001 [3] Miroslav Virius: C# pro zelenáče, Neokortex 2002 [4] Frank Eller: C# začínáme programovat, Grada 2002 [5] Eric Gunnerson: Začínáme programovat v C#, Computer Press, 2001 [6] Tom Archer: Myslíme v jazyku C# , Grada 2002 [7] Robin A. Reynolds-Haertle: OOP Objektově orientované programování krok za krokem, idnes 2002 [8] Meilir Page-Jones: Základy objektově orientovaného návrhu v UML , Grada 2001 [9] Herbert Schildt: Java2 Příručka programátora , SoftPress 2001
2.11.11
Základy objektově orientovaného programování (OOP)
41/41