1.
Seriál Učíme OOP
Rudolf Pecinovský Amaio Technologies, Inc.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 1 z 27
1.1. Nejprve trocha teorie
Strana 2 z 27
Úvod Tento článek je úvodním dílem seriálu, ve kterém se pokusím ukázat, jak lze učit objektově orientované programování (OOP). Ve svých dosavadních článcích jsem se prozatím snažil vysvětlit, proč musíme naše svěřence učit OOP a zároveň se pokoušel naznačit i některé základní atributy této výuky (doporučený jazyk, doporučené vývojové prostředí, systém vyhotovování a distribuování domácích úkolů, …). Tento seriál se již nebude zabývat otázkou proč učit OOP, ale soustředím se plně na otázku jak. Budu vás průběžně seznamovat s lekcemi, které jsem připravil pro své svěřence v kroužku pokročilého programování na ZŠ Pod Marjánkou. V tomto kroužku mám děti, které navštěvují 3. až 7. třídu a které již zvládly programování v Baltíkovi na úrovni učebnice, kterou jsem pro firmu SGP před pár lety napsal. O dalších požadavcích, které na ně mám, jste se mohli dočíst v přihlášce, která byla publikována i zde na České škole. Máte-li chuť, vydejte se s námi do nového programátorského světa. Od čtenářů nebudu předpokládat žádné speciální znalosti – bude stačit, když budou mít zvládnutého Baltíka na úrovni knížky Baltík – učebnice programování nejen pro děti. Abych umožnil proniknout do OOP i těm, kteří dávají přednost jinému programovacímu jazyku než Javě, kterou jsem zvolil já, budu se snažit psát tak, abych (pokud to půjde) minimalizoval závislost popisované látky na použitém programovacím jazyce. Dopředu bych se chtěl omluvit, že tento text nebude dokonalou učebnicí s vychytanými neduhy, protože bude vznikat za chodu. Může se proto stát, že si při výkladu nějaké pozdější partie uvědomím, že jsem vám měl v některé z minulých kapitol něco vyložit, takže budu muset výklad občas přetrhnout drobnými návraty k dříve vyložené látce. Stejně tak není vyloučeno, že v průběhu výkladu budu muset lehce upravovat dříve publikované demonstrační programy. Nekamenujte mne za to, prosím; je to cena za to, že dostanete text do ruky co nejdříve. Vyjde-li kurz někdy knižně, mělo by to tam být již všechno opraveno. V průběhu kurzu budeme vytvářet řadu programů. Abyste je nemuseli všechny psát, budou programu uvedené v textu připraveny ke stažení na adrese http://vyuka.pecinovsky.cz. Objevíte-li v kurzu či jeho doprovodných materiálech jakékoliv nesrovnalosti, neostýchejte se ozvat na adresu
[email protected].
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 2 z 27
1.1. Nejprve trocha teorie
Strana 3 z 27
1. Třídy a objekty Obsah 1.1
Nejprve trocha teorie......................................................................................................... 4 Třídy a jejich instance ..................................................................................................................................... 4 Zprávy ............................................................................................................................................................... 5
1.2
Instalace prostředí BlueJ .................................................................................................. 6 Java 2 SDK ....................................................................................................................................................... 6 BlueJ ................................................................................................................................................................. 7 Projekty........................................................................................................................................................... 10
1.3
Třídy a instance v praxi................................................................................................... 12 Vytváříme svou první instanci...................................................................................................................... 12 Pravidla pro tvorbu identifikátorů v jazyce Java ........................................................................................ 13 Vytváříme svou první instanci – pokračování............................................................................................. 14 Posíláme instanci zprávu.............................................................................................................................. 16 Vytváříme další instance............................................................................................................................... 16
1.4
Parametry a jejich typy.................................................................................................... 16 Vyvolání konstruktoru s parametry ............................................................................................................. 17 Posílání zpráv s parametry ........................................................................................................................... 19
1.5 1.6
Metody třídy ..................................................................................................................... 21 Metody vracející hodnotu ............................................................................................... 22 Návratová hodnota objektového typu ......................................................................................................... 22
1.7 1.8 1.9
Instance versus odkaz .................................................................................................... 23 Výlet do nitra instancí ..................................................................................................... 24 Shrnutí – co jsme se v kapitole naučili .......................................................................... 26 Nově zavedené termíny (abecedně)............................................................................................................. 26 Důležité informace......................................................................................................................................... 26
Všechny programy, které vytváříme, jsou simulací našeho okolního světa. Okolní svět je světem objektů. Budeme-li chtít, aby naše programy modelovaly tento svět co nejvěrněji, měly by být schopny modelovat obecné objekty spolu s jejich specifickými vlastnostmi a schopnostmi. Kvalita programu a rychlost jeho tvorby je velice úzce svázána s hladinou abstrakce, kterou při jejich tvorbě používáme. Budeme-li např. programovat ovládání robota, bude pro nás výhodnější jazyk, v němž můžeme zadat příkazy typu „zvedni pravou ruku“, než jazyk, v němž musíme vše vyjadřovat pomocí strojových instrukcí. Máme-li proto být schopni rychle vytvářet kvalitní programy, měli bychom mít k dispozici jazyk, jehož jazykové konstrukce nám umožní co nejvyšší míru abstrakce, při níž se můžeme vyjadřovat tak, abychom mohli přirozeně popsat modelovanou skutečnost. Všechny moderní programovací jazyky se honosí přídomkem „objektově orientované“. Tím se nám snaží naznačit, že nabízejí konstrukce, které umožňují rozumně modelovat náš okolní, objekty tvořený svět.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 3 z 27
1.1. Nejprve trocha teorie
Strana 4 z 27
1.1 Nejprve trocha teorie Než se vrhneme na vlastní programování, povíme si nejprve trochu o nejdůležitějších termínech, s nimiž se budeme v dalším výkladu setkávat. Abych vás tou teorií příliš neunavoval, tak tyto termíny opravdu jen zavedu a nebudu je nijak rozpitvávat. Postupně je pak podrobněji vysvětlím na příkladech v dalším textu. Důležité je nyní pouze to, abyste získali základní, rámcovou představu, co daný termín znamená.
Třídy a jejich instance Objekty, s nimiž se ve svém okolí setkáváme, můžeme rozdělit do kategorií, které v programování označujeme jako třídy. Vlastní objekty pak označujeme jako instance jejich třídy – např. židle, na které sedíte, je instancí třídy židlí. Mohli bychom tedy říci, že instance (objekt) je nějakou konkrétní realizací své třídy (židle, na které sedím, je konkrétní realizací obecné židle). Třídy popisují společné vlastnosti svých instancí. Zdá-li se nám, že uvnitř třídy existuje skupina objektů, které mají nějaké zvláštní vlastnosti, můžeme pro ně definovat nějakou speciální třídu, která bude podtřídou obecnější třídy, tzv. nadtřídy. (Když jsem se již zmínil o židlích, můžeme mezi nimi vyčlenit např. třídu kolečkových židlí, která bude podtřídou třídy židlí.) Podtřída bývá často označována jako dceřinná třída nebo odvozená třída a její nadtřída pak jako rodičovská třída. (V našem příkladu je třída kolečkových židlí dceřinnou třídou třídy židlí a naopak třída židlí je rodičovskou třídou třídy kolečkových židlí.) Třída může mít většinou několik instancí (třídy s jedinou povolenou instancí – jedináčkem – jsou spíše výjimkou). Na druhou stranu každý objekt je vlastní instancí právě jedné třídy – té, která jej „porodila“. Současně jej lze považovat za instanci kteréhokoli z jejích rodičů (prarodiče se v OOP počítají mezi rodiče). Židle, na které sedím, je tedy podle předchozího výkladu vlastní instancí třídy kolečkových židlí, ale v případě potřeby ji mohu považovat i za instanci obecné třídy židlí a kdybych šel dál i třídy nábytku (rodičovská třída třídy židlí) a obecných objektů (rodičovská třída nábytku). Odbočka pro šťouraly: Tady se nám programování zdánlivě trošku odchyluje od toho, co známe z okolního světa. Mnohé z vás asi napadlo, že vedle kolečkových židlí bychom mohli mít i např. židle kovové nebo čalouněné, a že vaši židli byste rádi jednou považovali za instanci třídy kolečkových židlí, podruhé za instanci třídy židlí kovových a potřetí za instanci židlí čalouněných. O tom, jak tento problém řešit, si povíme později. Prozatím se na to dívejte tak, že objekt mohla „porodit“ pouze jediná třída – ta, jejíž je daný objekt vlastní instancí.
Pro znázornění hierarchie tříd (tj. pro znázornění, kdo je čím rodičem a potomkem) se používá grafický jazyk UML (Unified Modeling Language – můžete se s ním seznámit např. v publikaci J. Schmuller: Myslíme v jazyku UML.Grada, 2001.) V něm se třídy znázorňují vodorovně rozdělenými obdélníky, v jejichž horní části je uvedené jméno třídy. Rodičovskou posloupnost pak znázorňujeme šipkami zakončenými nevyplněným trojúhelníkem, které vedou od dceřinných tříd k jejich rodičům. Náš předchozí příklad s židlemi bychom v jazyku UML znázornili např. tak, jako na obrázku 1.1. J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 4 z 27
1.1. Nejprve trocha teorie
Strana 5 z 27
Obrázek 1.1: Hierarchie rodičů a prarodičů kolečkové židle zapsaná v UML. Poznámka: Protože programové prostředí BlueJ, které budu při svém výkladu používat, se s češtinou, bohužel, příliš nekamarádí, budu v textech programů používat názvy bez háčků a čárek. Jakmile autoři v některé z příštích verzí prostředí tuto chybičku napraví, začnu „nabodeníčka“ používat.
Zprávy Objekty si mohou navzájem posílat zprávy, ve kterých se žádají o různé služby, přičemž onou službou může být často jen informace. (Můžeme se např. židle zeptat, je-li čalouněná. V praxi bychom to realizovali nejspíše tak, že bychom k ní poslali upřený pohled, v programu k ní vyšleme zprávu.) Objektový program je pak množinou objektů, které si navzájem posílají zprávy. V objektovém programování proto neplatí občas slýchaná definice, že program je posloupnost příkazů. Chcete-li se naučit programovat objektově, musíte nejprve tuto definici zapomenout. Historická odbočka: Definice, že program je zapsaná posloupnost příkazů, platila pro první tři zkonstruované počítače: Babageův Analytical Engine z poloviny devatenáctého století (to není překlep, ten počítač byl opravdu konstruován okolo roku 1850), Zuseovy počítače z konce třicátých let minulého století a Aikenův Mark 1 z počátku let čtyřicátých. Avšak programy pro známý ENIAC z poloviny čtyřicátých let minulého století by bylo lze označit za posloupnost příkazů jen s velkým sebezapřením, protože obsahoval řadu paralelně pracujících jednotek které si navzájem předávaly informace. Jeho programování však bylo natolik časově náročné, že jej později převedli na von Neumannovu koncepci, takže v druhé polovině jeho života již pro něj definice programu jako posloupnosti příkazů platila. V průběhu padesátých let došlo k obrovskému rozmachu nejen počítačů, ale také teorie programování a programátorských technik. Na počátku šedesátých let se tak začalo hromadně používat paralelní, událostmi řízené programování, a takovéto programy bychom za posloupnost příkazů považovat neměli. Posloupností příkazů nebyly ani programy psané v objektově orientovaných jazycích let sedmdesátých (např. Smalltalk) a už vůbec ne v logických programovacích jazycích let osmdesátých (např. Prolog). Je samozřejmé, že většina programů se na konec transformuje na posloupnost příkazů ve strojovém kódu, jenže my bychom měli při návrhu a realizaci svých programů zůstávat na optimální hladině abstrakce, a tam pravidlo o posloupnosti příkazů již v současné době většinou neplatí.
Na dotaz, co je to program, většinou odpovídám, že je to předpis, jak splnit zadanou úlohu, zapsaný v nějakém programovacím jazyce (dokud není zapsaný v programovacím jazyce, není to program, ale algoritmus). Tato definice je možná přesná (a bude nejspíš platit stále), nicméně je tak obecná, že je pro naše účely prakticky nepoužitelná. Definujme si proto, že objektově orientovaný proJ01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 5 z 27
1.2. Instalace prostředí BlueJ
Strana 6 z 27
gram je v nějakém programovacím jazyce zapsaný popis použitých tříd, objektů a zpráv, které si tyto objekty posílají, doplněný u složitějších programů ještě o popis umístění programů na jednotlivých počítačích a jejich svěření do správy příslušných služebních programů (např. operačních systémů či aplikačních serverů). Terminologická odbočka: Budete-li slyšet programátory velkých aplikací hovořit o „deploymentu“, tak vězte, že hovoří o výše zmíněném rozmísťovacím aspektu svých programů.
Jak je z uvedené definice patrné, přechodem na objektové programování vstupujete do jiného programátorského vesmíru. Do vesmíru, v němž sice použijete mnohé z toho, co jste se naučili při studiu klasického programování, ale v němž se základní úvahy o koncepci a konstrukci programu ubírají naprosto jinými cestami, než na které jste byli doposud zvyklí.
1.2 Instalace prostředí BlueJ Po teoretickém úvodu bychom měli začít s praxí. Abychom mohli vytvářet programy, potřebujeme k tomu vývojové prostředí. Pro účely tohoto kurzu jsem jako nejvýhodnější zvolil prostředí BlueJ, které nabízí několik vlastností, které se nám budou při výkladu základů OOP hodit. Toto prostředí bylo sice původně vyvinuto pro výuku, ale jak se můžete na stránkách http://www.bluej.org přesvědčit, jeho vlastnosti přivedly řadu programátorů k tomu, že je začali používat i pro vývoj menších profesionálních aplikací. Tito programátoři oceňují zejména jeho malou paměťovou náročnost (BlueJ vystačí se 48 MB RAM, zatímco běžná profesionální vývojová prostředí požadují minimálně 256 MB RAM) a originální, jinde nenabízené možnosti ladění programů. Podívejme se nyní, jak toto vývojové prostředí zprovozníme.
Java 2 SDK Vývojové prostředí pracuje na platformě Java. Abyste je mohli používat, musíte mít nejprve tuto platformu nainstalovánu. Protože je to vývojové prostředí a ne obyčejný program, požaduje instalaci Java 2 SDK (Software Development Kit; někdy je označováno také jako JDK – Java Development Kit), což je platforma doplněná o základní vývojové nástroje (překladač, generátor dokumentace a další). BlueJ přitom požaduje nejméně verzi 1.3. Tady si zajásají uživatelé počítačů Macintosh, protože novější verze operačního systému MacOS mají akceptovatelnou verzi JDK již instalovanou jako součást operačního systému. Ti ostatní musí postupovat podle následujících instrukcí. Poznámka: Nespleťte si JDK s JRE (Java Runtime Environment), které sice obsahuje kompletní balík programů potřebný pro spouštění aplikací v Javě, ale chybí mu právě takové drobnosti, jako překladač nebo generátor dokumentace, bez kterých nic nevyvinete.
Pokud jste s Javou doposud nepracovali (tj. ještě žádné JDK instalované nemáte), doporučuji vám stáhnout a instalovat nejnovější verzi 1.4.1_01, kterou naleznete na adrese J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 6 z 27
1.2. Instalace prostředí BlueJ
Strana 7 z 27
http://java.sun.com/j2se/1.4.1/download.html. Na stránce si můžete vybrat mezi verzemi pro Windows a Linux. Počítejte však s tím, že stahovaný soubor má přes 36 MB a po rozbalení bude mít asi 2krát tolik. Umíte-li anglicky a máte-li rozumně rychlé připojení, doporučuji vám navíc stáhnout na téže stránce i dokumentaci, avšak znovu vás musím připravit na to, že stahovaný soubor má přes 30 MB po rozbalení bude samotná dokumentace zabírat na disku okolo 180 MB. Máte-li proto někde ve svém okolí někoho, kdo v tomto jazyku programuje (může to být i firma), bude možná výhodnější požádat jej o vypálené CD. Při té příležitosti vám může vypálit i nějaké vývojové prostředí, ve kterém budete pracovat poté, co BlueJ opustíte. JDK spolu s různými vývojovými prostředími se jednou za čas objeví také na CD, která jsou přibalena k některým počítačovým časopisům. Při instalaci pamatujte na to, že programy v Javě nemívají rády mezery v názvech souborů. Neinstalujte proto balík do oblíbené složky Program files, ale do nějaké složky bez mezer v názvu. Jste-li stejně jako já nepřátelé zaplácaného kořenového adresáře, doporučuji vám na svém příkazovém disku zřídit složku \Java\ a všechny instalované javové programy pak směřovat do ní – já mám např. JDK ve složce E:\Java\j2sdk1.4.1.
BlueJ Vývojové prostředí BlueJ si můžete zdarma stáhnout na adrese http://www.bluej.org/download/download.html. Není to již taková obluda jako JDK, poslední verze 1.2.2 má pro Windows pouhých 1,3 MB, pro MacOS dokonce jen 750 KB a pro ostatní systémy asi 800 KB. Součástí standardní distribuce je i česká lokalizace. Přiznám se však, že se mi některé překlady nelíbily (jak se autor přiznal, dělal je poměrně ve spěchu), takže jsem lokalizaci trošku upravil. BlueJ má proto nyní dvě české lokalizace. Tu moji si můžete stáhnout na adrese Tamtéž, konkrétně na adrese http://java.pecinovsky.cz/bluej/lib_rup.zip. http://java.pecinovsky.cz/bluej/BlueJ_Tutorial_Czech_RUP.pdf najdete i upravený překlad úvodního tutoriálu, který si můžete také stáhnout. Při instalaci opět myslete na nesnášenlivost některých programů s mezerami v názvu a nabídněte programu nějakou „nemezerovou“ složku – já jej mám instalován do složky E:\Java\BlueJ\. Budete-li chtít používat moji lokalizaci, zkopírujte obsah staženého souboru lib_rup.zip do podsložky lib kořenové složky prostředí BlueJ (na mém počítači by to bylo do složky E:\Java\BlueJ\lib). Při nastavování parametrů rozbalování dohlédněte na to, aby se vytvořily i příslušné podsložky – konkrétně složka rup, její podsložka templates a její podsložka newclass (viz obr. 1.2). Při vlastním rozbalování se pak nelekněte, až se váš rozbalovací program zeptá, jestli má ve složce lib přepsat soubory bluej.defs a moe.defs (nezeptá-li se vás, dohlédněte, aby se přepsaly). První obsahuje informace o nastavené lokalizaci, druhý některé parametry zabudovaného editoru. Rozbalením lokalizačního souboru byste měli ukončit operace potřebné k instalaci prostředí a můžete je spustit.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 7 z 27
1.2. Instalace prostředí BlueJ
Strana 8 z 27
Obrázek 1.2: Složky, v nichž je instalován BlueJ s lokalizací rup.
Po prvním spuštění program možná otevře dialogové okno BlueJ Launcher, v němž se vás zeptá na umístění JDK. V tomto dialogovém okně vypíše všechna JDK, která na vašem počítači identifikuje. Nalézá-li se mezi nimi to, s nímž chcete pracovat, klepněte na příslušný řádek a pak stiskněte tlačítko Launch BlueJ.
Obrázek 1.3: Zadání použitého JDK
Někdy se stane, že BlueJ žádné JDK nenajde a okno bude prázdné, nebo v něm není to JDK, jež byste rádi použili. Pak stiskněte tlačítko Advanced, čímž rozbalíte spodní část okna, která nabízí další možnosti.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 8 z 27
1.2. Instalace prostředí BlueJ
Strana 9 z 27
Obrázek 1.4: Nalezení použitého JDK
Předpokládám, že víte, kam jste JDK instalovali. Pak stačí stisknout tlačítko Browse for a specific Java version… a v následně otevřeném dialogovém okně pro otevření souboru nalézt požadované JDK. Počítejte ale s tím, že tentokrát se již BlueJ nespokojí se složkou, v níž je celé JDK instalováno (a kterou uvádí v horní části okna), ale bude chtít ukázat přímo soubor java.exe, který se nalézá v podsložce bin – při použití J2SDK 1.4.1 by to tedy na mém počítači byl soubor E:\Java\j2sdk1.4.1\bin\Java.exe. Po úspěšném zadání JDK stiskněte tlačítko Launch BlueJ a program dialogové okno zavře, po chvíli zobrazí své zaváděcí okno a po další chvíli se BlueJ natáhne a spustí. S výše popsaným dotazem vás již příště obtěžovat nebude. Pokud však své JDK později inovujete, je možno BlueJ přesvědčit, aby je začal používat. Popis postupu, jak toho dosáhnout, však překračuje rámec tohoto textu.
Obrázek 1.5: Zaváděcí okno programu BlueJ J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 9 z 27
1.2. Instalace prostředí BlueJ
Strana 10 z 27
Projekty V BlueJ nebudeme pracovat s programy, ale s projekty. (Tak tomu je ve všech moderních vývojových prostředích.) Projekt může obsahovat jeden program (tj. něco, co spustíme a ono to běží) nebo několik programů – to podle toho, jak se nám to zrovna hodí. Poznámka: Žákům ve svém kroužku to vysvětluji na příkladu vítězného projektu mladší kategorie z letošní programátorské soutěže BB2002. Byl jím soubor deskových her, který obsahoval 5 programů: Dámu, Piškvorky, Revesi, Hlavní program umožňující volbu hry a skript umožňující, aby Baltík spustil jiný program včetně programu napsaného pro Baltíka.
S programem BlueJ přichází několik projektů, které najdete v jeho podsložce examples. Doporučuji vám však, abyste si pro svoje projekty a projekty, které budou součástí tohoto seriálu, zřídili novou složku (nezapomeňte na pravidlo o zakázaných mezerách v názvech složek na cestě). Dětem v kroužku např. doporučuji, aby si na datovém disku zřídili složku Java s podsložkami Texty a Projekty. Do složky Texty si vkládají text tohoto seriálu a případně další texty týkající se programování a Javy, ve složce Projekty pak zřizují pro každý projekt novou složku, do níž umísťují všechny soubory, které k němu patří. Jakmile složku pro své projekty zřídíte, můžete si do ní hned stáhnout úvodní projekt 01_tvary, který najdete na adrese http://vyuka.pecinovsky.cz/index.htm. Spusťte pak BlueJ, zadejte příkaz Projekt → Otevřít a v následně otevřeném dialogovém okně ukažte programu složku s projektem (viz obr. 1.6).
Obrázek 1.6: Otevření existujícího projektu
Na obrázku si všimněte, že ikony projektů (přesněji ikony složek, v nichž je uložen projekt) vypadají jinak než ikony obyčejných složek. BlueJ totiž do složky, ve které budou soubory jeho projektu, přidá své vlastní soubory, do nichž si např. ukládá rozmístění tříd v diagramu tříd a další J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 10 z 27
1.2. Instalace prostředí BlueJ
Strana 11 z 27
tu, přidá své vlastní soubory, do nichž si např. ukládá rozmístění tříd v diagramu tříd a další informace. Podle přítomnosti těchto souborů pak pozná, zda se jedná o složku s jeho projektem nebo o nějakou obyčejnou složku. Po otevření projektu by okno BlueJ mělo vypadat obdobně jako na obrázku 1.7. Bílý obrázek listu papíru vlevo nahoře je symbol textového souboru se základním popisem celého projektu. Když na něj poklepete, otevře se okno editoru, v němž si budete moci tyto informace přečíst a v případě potřeby je i upravit či doplnit.
Obrázek 1.7: Okno BlueJ po otevření projektu 01_tvary_0
Sada čtyř obdélníků s čárkovanými šipkami znázorňuje třídy našeho projektu zakreslené podle konvencí jazyka UML (vybarvení obdélníků do konvence nepatří, ale zvyšuje přehlednost a názornost diagramu). Čárkované šipky vedoucí od těchto tříd ke třídě Platno naznačují, že tyto třídy třídu Platno používají (my víme, že se na plátno kreslí). Obrázek tříd a jejich vzájemných závislostí tvoří diagram tříd našeho projektu. Polohu jednotlivých tříd v diagramu můžete měnit. Jsou-li navzájem spojeny šipkami, BlueJ bude vaše přesuny sledovat a po umístění obrázku třídy do nové pozice šipky vždy příslušně překreslí. Můžete si tak diagram upravit tak, aby byl co nejpřehlednější a nejnázornější. Šrafování spodní části obdélníků symbolizuje to, že třídy ještě nejsou přeloženy. To lze snadno napravit: stiskněte tlačítko Přeložit v levé části aplikačního okna. Uvidíte, jak jedna třída za druhou ztmavne (tím prostředí naznačuje, že se překládá), aby pak opět zesvětlela a její šrafování zmizelo (již je přeložena). Od této chvíle můžete třídu používat.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 11 z 27
1.3. Třídy a instance v praxi
Strana 12 z 27
Poznámka: Pokud jste doposud pracovali pouze s Baltíkem, tak jste se s nutností překladu svých programů ještě nesetkali. Baltík totiž pročítá váš program příkaz za příkazem a každý ihned provede (interpretuje). Řadíme jej proto mezi interprety. Společnou nevýhodou interpretů je, že na interpretaci programu vyplýtvají spoustu času a programy proto běží pomalu. Většina jazyků proto používá jiný mechanizmus: program se nejprve přeloží do podoby, které stroj rozumí, a ta se pak stroji předhodí k vykonání. Nevýhodou překládaných programů je to, že je po každé úpravě musím před prvním spuštěním nejprve přeložit. Tato nevýhoda je však bohatě vykoupena zrychleným během spuštěného programu a také tím, že překladač má více času na to, aby zkontroloval, jestli jsme někde neudělali nějakou chybu. Chyby zjištěné již při překladu se totiž lépe hledají a snáze odstraňují. Překládané jazyky proto bývají navrženy tak, aby se co nejvíce logických chyb projevilo jako syntaktické chyby, které se odhalí již ve fázi překladu. Tak je navržena i Java.
1.3 Třídy a instance v praxi Vytváříme svou první instanci V jazyku Java (a dalších současných objektově orientovaných jazycích – C++, C#, VisualBasic.NET) vytváříme instance tříd pomocí operátoru new, za nímž uvedeme název třídy a dvojici kulatých závorek. Tím zavoláme speciální funkci, které říkáme konstruktor a která danou instanci vytvoří. My pak obdržíme na tuto instanci odkaz, prostřednictvím nějž se na ni budeme obracet. Poznámka: V moderních programovacích jazycích náš program nikdy neobdrží instanci, kterou vytvořil. Obdrží pouze odkaz na tuto instanci. Vlastní instance je zřízena někde na haldě (heap – oblast paměti vyhrazená právě pro ukládání vytvořených instancí), kterou má na starosti správce paměti (garbage collector – doslova popelář). Ten se stará o to, aby instance, které již nikdo nepotřebuje, nezabíraly v paměti zbytečně místo. Některé studie tvrdí, že toto řešení zvyšuje produktivitu programátorské práce oproti práci v klasickém C++ minimálně dvojnásobně.
Vyzkoušíme si vše v praxi. V našem projektu máme pouhé 4 třídy: třídu Platno, jejíž instance představuje kreslicí plátno a třídy Obdelnik, Trojuhelnik a Elipsa, jejichž instance představují objekty, které lze na toto plátno nakreslit. Vyjmenované třídy jsou zobrazeny jako rozdělené obdélníky (jak jsem říkal, BlueJ zakresluje třídy podle pravidel jazyka UML). Zkusme vytvořit např. instanci obdélníku. Klepněte pravým tlačítkem na třídu Obdélník. Rozbalí se místní nabídka, v jejíž horní části je seznam konstruktorů. Klepněte na první z uvedených konstruktorů, tj. ten bezparametrický (za názvem třídy má prázdné závorky).
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 12 z 27
1.3. Třídy a instance v praxi
Strana 13 z 27
Obrázek 1.8: Vytvoření instance třídy Obdelnik bezparametrickým konstruktorem.
Otevře se dialogové okno (viz obr. 1.9), v němž vás BlueJ seznámí se základními údaji o vyvolávaném konstruktoru a zároveň se vás zeptá na název odkazu na vytvářený objekt. Tento název musí splňovat pravidla pro vytváření identifikátorů v jazyce Java (kdo to ještě neví, tak mu prozradím, že v programovacích jazycích se nehovoří o názvech, ale o identifikátorech)
Obrázek 1.9: Dialogové okno po zavolání bezparametrického konstruktoru.
Pravidla pro tvorbu identifikátorů v jazyce Java Identifikátory čehokoliv musí v jazyku Java vyhovovat následujícím pravidlům: smí obsahovat pouze písmena, číslice a znaky „_“ (podtržítko) a „$“ (dolar), nesmí začínat číslicí, nesmí být shodné s žádným klíčovým slovem, tj. s žádným ze slov: abstract byte catch continue else
assert byvalue* char default extends
boolean case class do false
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
break cast* const* double final Strana 13 z 27
1.3. Třídy a instance v praxi finally generic* import interface null private return switch throws var*
Strana 14 z 27 float goto* inner* long operator* protected short synchronized transient void
for if instanceof native outer* public static this true volatile
future* implements int new package rest* super throw try while
Délka identifikátorů není v jazyku Java omezena (to u řady jiných programovacích jazyků neplatí). Poznámka 1: Java patří mezi jazyky, kterým záleží na tom, zda napíšete identifikátor velkými či malými písmeny. Identifikátory něco, Něco a NĚCO jsou proto chápány jako tři různé identifikátory. Poznámka 2: Teoreticky podle definice jazyka patří mezi písmena všechny znaky včetně českých, ruských či japonských, nicméně řada prostředí (a BlueJ je prozatím bohužel mezi nimi) se s neanglickými znaky nekamarádí, takže je prozatím v našich programech nebudu používat. Jakmile autoři prostředí svůj program opraví a ten bude schopen znaky s diakritikou bez problému akceptovat, začnu je používat i v tomto kurzu.
Vytváříme svou první instanci – pokračování Protože prozatím nemáme žádný pádný důvod něco měnit, můžeme akceptovat název, který nám program nabídne. Po potvrzení názvu se vytvoří instance třídy Obdelnik a odkaz na ni se umístí do zásobníku odkazů. Položky v zásobníku odkazů můžeme považovat za proměnné, v nichž jsou uloženy příslušné odkazy. Název proměnné je uveden v prvním řádku červeného zaobleného obdélníku, název třídy, na jejíž instanci odkaz ukazuje, pak v řádku druhém.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 14 z 27
1.3. Třídy a instance v praxi
Strana 15 z 27
Obrázek 1.10: Odkaz na první instanci v zásobníku odkazů.
Konstruktor při vytváření instance zároveň zařídí, aby se na plátně zobrazil příslušný obrázek a pokud ještě plátno neexistuje, tak aby se vytvořilo (tj. požádá třídu Platno, aby vytvořila svoji instanci), protože jinak by nebylo na co kreslit. Dalším výsledkem tedy je, že se otevře okno plátna a na něm bude zobrazen náš obdélník.
Obrázek 1.11: Okno plátna s nakresleným obdélníkem.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 15 z 27
1.4. Parametry a jejich typy
Strana 16 z 27
Poznámka 1: Pokud okno plátna nevidíte, bude asi schované pod nějakým jiným oknem – dost možná právě pod oknem BlueJ. Zobrazíte je buď tak, že na panelu úloh klepnete na jeho tlačítko, anebo že budete postupně minimalizovat či posouvat otevřená okna, až okno plátna najdete. Poznámka 2: Třída Platno je zrovna třídou, která vám nedovolí vytvořit její instanci prostřednictvím konstruktoru (tj. pomocí operátoru new), protože trvá na tom, aby její instance byla jedináček. Proto se musíme spolehnout na to, že se s ní třídy Obdelnik, Elipsa a Trojuhelnik dokáží dohodnout, aby vše fungovalo tak, jak to fungovat má.
Posíláme instanci zprávu Nyní zkusíme nově vytvořenému obdélníku poslat nějakou zprávu. Klepněte pravým tlačítkem myši na červený zaoblený obdélník s odkazem. Rozbalí se poměrně dlouhá místní nabídka, která má nahoře černé položky zastupující zprávy (vysvětlení proč vypadají právě takto si necháme na později) a dole červené položky zastupující příkazy pro vývojové prostředí. Zadejte příkaz void posunVpravo() – a ejhle, obdélník se po plátně opravdu posune vpravo.
Vytváříme další instance Říkali jsme si, že běžná třída může mít více instancí. Tak si to hned vyzkoušíme a vytvoříme další obdélník – požádejte třídu Obdelnik stejným způsobem o druhý obdélník. Potvrďte opět nabízený název a zkontrolujte, že se v zásobníku odkazů objevil příslušný odkaz a že se v levém horním rohu plátna opravdu vytvořil druhý obdélník. Úkol: Vytvořte instance dalších tříd. Pošlete jednotlivým instancím zprávy void posunVpravo(), void posunVlevo(), void posunNahoru() a void posunDolu() a ověřte si, že na každou zprávu reaguje ten objekt, kterému jste ji poslali.
1.4 Parametry a jejich typy Zkusíme si vytvořit ještě další instanci třídy Obdelnik. Abychom se však neopakovali, použijeme nyní některý z dalších konstruktorů. Ty již mají v závorkách za názvem třídy, jejíž instanci vytvářejí, uveden seznam parametrů, které musíme při jejich volání zadat. V místní nabídce (viz obr. 1.8) je každý parametr zastoupen svým názvem, jenž naznačuje, jaký údaj konstruktor v daném místě očekává. Abych s ním však mohl následně pracovat, potřebuje, aby byl zadaný údaj správného typu. Typ údaje popisuje, co je daný údaj zač. Svůj typ mají nejenom parametry, ale veškerá data, se kterými program pracuje. Java (a naprostá většina ostatních moderních jazyků) trvá na tom, aby
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 16 z 27
1.4. Parametry a jejich typy
Strana 17 z 27
byl u každého údaje předem znám jeho typ. Za to se nám odmění tím, že odhalí řadu našich chyb již v zárodku. V nejbližších kapitolách se budeme setkávat se třemi typy: int označuje typ celých čísel, která se mohou pohybovat přibližně v rozsahu od -2 000 000 000 do +2 000 000 000, String definuje typ znakových řetězců; aby je program správně rozpoznal, musíte je vždy zadávat uzavřené mezi uvozovkami – např. "Znakový Řetězec", boolean definuje typ logických hodnot, které mohou nabývat pouze hodnot true (pravda, ano, …) a false (nepravda, ne, …).
Vyvolání konstruktoru s parametry Zkusme tedy zavolat 5parametrový konstruktor. Po zadání příslušného povelu se objeví velké dialogové okno (viz obr. 1.12), v němž nás BlueJ žádá nejenom o zadání (nebo alespoň potvrzení) názvu odkazu na vytvářený objekt, ale také o hodnoty jednotlivých parametrů.
Obrázek 1.12: Okno konstruktoru s parametry
Horní část okna zobrazuje popis funkce volaného konstruktoru spolu s popisem významu jednotlivých parametrů. Neděste se toho, že popis je trochu kryptický (zašifrovaný) – je to opsaná část pro-
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 17 z 27
1.4. Parametry a jejich typy
Strana 18 z 27
gramu sloužící k tvorbě dokumentace. Pamatujte si, že za každým @param následuje název parametru a jeho popis. Poznámka: V této části nemusí být vždy uvedeny všechny parametry. Jsou tam jen ty, které se tvůrce programu rozhodl popsat. Berte proto tento návod pouze jako pomůcku a smiřte se s tím, že programy tvůrců, kteří jsou líní dělat dokumentaci, je nabízet nebudou.
Tučný text nad vodorovnou dělící čarou budeme označovat jako hlavička konstruktoru. V hlavičce je uveden seznam všech parametrů (tentokrát opravdu všech – je-li parametrů více, jsou jejich deklarace odděleny čárkami.), přičemž u každého parametru je uveden nejprve jeho typ a za typem jeho název. Typ i název každého parametru je pak zopakován u vstupního pole, do nějž budete zadávat hodnotu tohoto parametru. Dejme tomu, že budeme opět akceptovat nabízený název odkazu a že náš třetí obdélník bude fialový, 25 bodů široký, 50 bodů vysoký a bude umístěn na souřadnicích [100;100]. Vstupní pole dialogového okna bychom pak vyplnili podle obrázku 1.13 (všimněte si uvozovek u zadávaného názvu barvy):
Obrázek 1.13: Vyplněné okno parametrického konstruktoru
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 18 z 27
1.4. Parametry a jejich typy
Strana 19 z 27
Posílání zpráv s parametry Konstruktory jsou pouze zvláštním druhem zpráv. Obdobně jako při volání konstruktorů zadáváme parametry i při posílání obyčejných zpráv. Dejme tomu, že bychom se rozhodli barevně odlišit druhý obdélník od prvního. Jednou z možností je zaslat druhému obdélníku zprávu, v níž jej požádáme, aby se přebarvil dejme tomu na černo. Otevřete proto jeho místní nabídku a zadejte v ní příkaz void setBarva(String). Terminologická poznámka: Zasílání zpráv se v programech v Javě realizuje prostřednictvím volání speciálních funkcí označovaných jako metody. Názvy metod pro nastavování nějakých charakteristik objektů začínají v Javě podle konvence slůvkem set, názvy metod pro zjišťování těchto charakteristik začínají slůvkem get a v případě, kdy se má vrátit informace typu ANO/NE, slůvkem is. Protože s těmito konvencemi některé nástroje počítají, budu je používat hned z počátku, abyste si na ně zvykli a nemuseli se něco přeučovat v okamžiku, kdy budete potřebovat použít nástroje, které používání těchto konvencí vyžadují. Za výše popsanými „předponami“ pak budu používat první pád, tj. např. setBarva a ne setBarvu. Poznámka k prostředí: U konstruktorů jsme si říkali, že BlueJ uvádí v nabídce názvy jednotlivých parametrů. Jak jste si možná všimli, v místní nabídce instancí uvádí naopak jejich typy. Na můj dotaz autoři uvedli, že to je historický důsledek nějakých starších rozhodnutí a slíbili, že to v příští verzi odstraní.
Podoba příkazu napovídá, že metoda setBarva(String) vyžaduje předání parametru, kterým je informace o požadované barvě. Tuto informaci přitom metoda bude chtít zadat ve formě textového řetězce. Po zadání příkazu proto BlueJ otevře dialogové okno, v němž nás o zadání parametru požádá, a zároveň vypíše informace o tom, jak má požadovaný parametr vypadat. Uposlechněte a zadejte textový řetězec s požadovanou barvou (nezapomeňte na uvozovky – viz obrázek):
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 19 z 27
1.4. Parametry a jejich typy
Strana 20 z 27
Obrázek 1.14: Volání metody s parametrem. Terminologická poznámka: Vedle hlavičky konstruktoru existuje i hlavička metody, ve které jsou uvedeny všechny základní informace potřebné pro její volání. Tuto hlavičku vypisuje BlueJ v dialogovém okně Volání metody nad vodorovnou dělící čáru. Poznámka: Možná jste si v místních nabídkách všimli, že některé metody mají stejný název a liší se pouze počtem a/nebo typem parametrů. (Programovací jazyky neumožňují definovat dvě různé metody se stejným názvem a seznamem typů parametrů.) Aby proto bylo vždy jasné, o které metodě (zprávě) hovořím, budu se snažit název metody vždy doplňovat závorkami se seznamem typů jejích parametrů.
Úkol: Zkuste nyní vytvořit i instance dalších tříd (trojúhelníků a elips) a vyzkoušejte si, jak budou reagovat na zprávy, které jim budete posílat. Zkuste pomocí příkazů vytvořit nějaký zajímavý obrázek. Poznámka: Smaže-li některý obrazec během přesunu část jiného obrazce, můžete narušený obrazec obnovit zasláním zprávy nakresli().
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 20 z 27
1.5. Metody třídy
Strana 21 z 27
1.5 Metody třídy Někdy potřebujeme zaslat zprávu, která se netýká jedné konkrétní instance, ale týká se celé třídy. Rodičovská třída totiž své instance neopouští, ale uchovává informace, které jsou pro všechny její instance společné a které mohou její instance kdykoliv využít. Zároveň také často poskytuje metody, které umožňují tyto informace ovlivnit nebo vykonat jinou akci, jež není svázána s žádnou její konkrétní instancí. Podívejme se např. na náš předchozí příklad s geometrickými tvary. Na příkaz presunXXX() se obrazce přesunou o předem stanovaný počet obrazových bodů směrem XXX. Velikost tohoto kroku je přitom pro všechny instance dané třídy stejná – je to právě ten druh informace, kterou instance sdílejí prostřednictvím své rodičovské třídy. Rozhodneme-li se proto velikost tohoto implicitního přesunu změnit, musíme poslat zprávu celé třídě. Podívejte se znovu na obrázek 1.8. Ve střední části místní nabídky třídy Obdelnik si můžete všimnout dvou položek, jejichž zadáním posíláme zprávu celé třídě. Zasláním zprávy getKrok() se třídy zeptáte na současnou velikost kroku, zasláním zprávy setKrok(int) nastavíte novou velikost tohoto kroku. Tato velikost pak bude platit pro všechny instance dané třídy, tj. i pro ty, které vznikly před tím, než jsme nastavili novou velikost kroku a které proto doposud používaly velikost původní. Úkol 1: Otevřete místní nabídku některé třídy a zadejte v ní příkaz void setKrok(velikost). V následně otevřeném dialogovém okně zadejte novou velikost kroku – dejme tomu 100 bodů – a vyzkoušejte, jak budou jednotlivé instance reagovat. Všimněte si, že se krok změnil pro všechny (staré i nové) instance dané třídy, avšak instance jiných tříd na něj vůbec nereagují a dál se přesouvají původně nastavenou velikostí kroku. Zkuste znovu změnit velikost kroku, avšak tentokrát pro jinou třídu. Nastavte jí krok např. na 5 bodů a znovu vše vyzkoušejte. Úkol 2: Velmi užitečnou metodou třídy bude pro vás při vašich experimentech metoda smaz() třídy Plátno. Po našich předchozích pokusech máte již plátno jistě zaplněné několika grafickými tvary. Zavolejte proto tuto metodu z místní nabídky třídy plátno a budete mít plátno čisté. Poznámka: Metoda smaz() smaže opravdu pouze plátno, tj. „natře“ je na bílo. V žádném případě neodstraňuje objekty z paměti – pouze smaže obrázek, který na plátno nakreslily. Můžete se o tom přesvědčit tak, že kterýkoliv z objektů, na nějž máte odkaz, požádáte, aby se znovu nakreslil, tj. zadáte v jeho místní nabídce příkaz void kresli(). Poznámka_pro_šťouraly: Metoda smaz() třídy Platno není pravou metodou třídy. Měla by to být správně metoda konkrétního plátna. Protože však víme, že toto plátno je jedináček, je z jistého úhlu pohledu jedno, jak metodu deklaruji. V našem programu je definována jako metoda třídy proto, abyste k ní měli snadný přístup a nemuseli kvůli smazání plátna pracně získávat odkaz na jeho instanci. Přizná-
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 21 z 27
1.6. Metody vracející hodnotu
Strana 22 z 27
vám, že hlediska správného programování je to nečisté, ale pro naše praktické účely je to výhodné.
1.6 Metody vracející hodnotu Metodu getKrok(), o níž jsem se před chvílí zmiňoval, jsme zatím nepoužili. Tato metoda se totiž od všech metod, o nichž jsme doposud hovořili, liší tím, že jejím úkolem není něco udělat, ale něco zjistit a předat nám zjištěnou informaci – tzv. návratovou hodnotu (někdy se používá také termín výstupní hodnota). Návratová hodnota metody má, stejně jako např. parametry, o nichž jsme hovořili před chvílí, svůj typ. Ten se uvádí před název metody, jejímž voláním realizujeme zaslání příslušné zprávy – tedy např. ze zápisu int getKrok() hned poznáme, že tato verze metody getKrok() nechce žádné parametry a vrátí nám celé číslo. Podívejme se, jak to vypadá v praxi. Otevřete opět místní nabídku třídy Obdelnik a zadejte v ní tentokrát příkaz int getKrok(). Protože metoda nemá žádné parametry, nebude se nás BlueJ na nic vyptávat. Provede, o co jsme jej požádali, a otevře dialogové okno (viz obr. 1.15), v němž nám oznámí výsledek (anglicky result) a informaci doplní o typ předávaného výsledku (v našem případě int).
Obrázek 1.15: Předání výstupní (návratové) hodnoty.
Návratová hodnota objektového typu Metody nemusejí vracet pouze celá čísla nebo řetězce. Mohou vracet objekt libovolného typu. K ukázce opět využijeme třídu plátno. V její místní nabídce jste si mohli všimnout příkazu Platno getPlatno(). Tento příkaz zavolá stejnojmennou metodu, která, jak je v příkazu uvedeno, vrátí Platno, tj. odkaz na instanci třídy Platno. To nám ukáže i dialogové okno s návratovou hodnotou (viz obr. 1.16), které naznačuje, že metoda vrací hodnotu, jež je odkazem na objekt, tj. na instanci nějakého objektového typu.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 22 z 27
1.7. Instance versus odkaz
Strana 23 z 27
Obrázek 1.16: Dialogové okno s návratovou hodnotou objektového typu.
Oproti obrázku 1.16 budou tlačítka v pravé části okna na počátku obdobně „mrtvá“ jako na obrázku 1.15. Stačí však klepnout na vracený odkaz – odkaz se podbarví a tlačítka vpravo obživnou tak, jak to ukazuje obrázek. Pomineme prozatím možnost si objekt prohlédnout (budeme se jí věnovat vzápětí) a požádáme pouze o odkaz. Stiskněte proto tlačítko Získat odkaz a následným stiskem tlačítka Zavřít dialogové okno zavřete. Jak se můžete přesvědčit, v zásobníku odkazů se objevil nový odkaz nazvaný result, který odkazuje na objekt typu Plátno. Vyzkoušejme jej. Otevřete místní nabídku nově zařazeného odkazu a zadejte v ní např. příkaz void setRozmer(int,int). V následně otevřeném dialogovém okně zadejte nové rozměry (např. 200, 200) a zadání potvrďte. Okno plátna vzápětí změní svůj rozměr na požadovanou hodnotu.
1.7 Instance versus odkaz Jak jsem již řekl na počátku našich hrátek s geometrickými tvary, třída Platno trvá na tom, že její instance bude jedináček. (Proto nám také nenabízí konstruktor.) Z toho tedy zákonitě vyplývá, že při každém volání metody getPlatno() dostaneme odkaz na stejnou instanci. Vyzkoušejme to. Pošlete třídě Platno znovu zprávu getPlatno() a opět zadejte v dialogovém okně, že chcete získat odkaz. V zásobníku odkazů se tak objeví další odkaz, tentokrát nazvaný result_2. Máme tedy dva odkazy, o nichž tvrdíme, že odkazují na stejný objekt. Přesvědčme se o tom. Požádejte jeden odkaz, aby jím odkazovaná instance změnila svůj rozměr a pak o totéž požádejte druhý odkaz (zadáte samozřejmě jiný rozměr). Obě dvě žádosti ovlivní velikost jednoho a toho samého okna. Oba dva odkazy totiž ukazují na jednu a tu samou instanci. Nesměšujte nikdy instanci s odkazem na ni! Až budete s objekty pracovat ve svých programech, pamatujte, že ve proměnných budete mít vždy pouze odkazy na objekty, s nimiž pracujete. Může se proto lehko stát, že bude několik proměnných odkazovat na stejný objekt, ale stejně dobře se může stát, že budete mít v nějaké proměnné uložen jediný dostupný odkaz na důležitý objekt, a když tento odkaz omylem přemažete, tak objekt bude sice dál existovat (a třeba dělat nějakou neplechu), ale vy se k němu již nikdy nedostanete.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 23 z 27
1.8. Výlet do nitra instancí
Strana 24 z 27
1.8 Výlet do nitra instancí Zatím jsme si ukazovali, jak instance reagují na zprávy, které jim posíláme. Zatím jsme si ale nic neříkali o tom, jak instance pozná, kde se má nakreslit, odkud se má přesunout nebo jak zjistí, jakou má její obrazec barvu. Jak jste jistě sami odhadli, instance uchovávají informace o svém vnitřním stavu. Pro tyto účely pro ně třída definuje potřebné konstanty a proměnné, které označujeme jako atributy instancí. Někdy se v literatuře setkáte také s termíny vnitřní proměnné nebo členské proměnné. Já však o nich budu v dalším textu hovořit výhradně jako o atributech. Své atributy může mít i celá třída – tyto atributy třídy pak všechny její instance sdílejí a jakákoliv jejich změna se ihned promítne do všech instancí dané třídy. U našich geometrických obrazců jsou atributy instancí jejich poloha, rozměr a barva. Atributem celé třídy je pak velikost kroku, o nějž se obrazec posune při zaslání bezparametrického povelu k posunu. Poznámka: Metody, jejichž názvy začínají magickými předponami set, get a is, jsou určeny právě ke zjišťování aktuálních hodnot atributů a k nastavování hodnot nových. Programátoři je často souhrnně označují jako „getry“ a „setry“, což bychom mohli otrocky přeložit jako „čteče“ a „nastavovače“. Já však budu v dalším textu používat termín čtecí a nastavovací metody, případně budu používat společný název přístupové metody, což vystihuje to, že prostřednictvím těchto metod přistupujeme k atributům.
Prozatím jsme o atributech hovořili pouze jako o něčem, co existuje, ale neměli jsme možnost se o tom přesvědčit. Hned to napravíme. Vyvolejte pravým tlačítkem myši místní nabídku některé instance a zadejte v ní povel Prohlížet.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 24 z 27
1.8. Výlet do nitra instancí
Strana 25 z 27
Obrázek 1.17: Okno prohlížeče objektů
Tímto povelem spustíte prohlížeč objektů (uživatelé Windows si mohou všimnout, že se na liště úloh objeví další aplikace), který otevře své okno a vypíše v něm hodnoty atributů příslušné instance spolu s hodnotami atributů třídy, jež „porodila“ objekt, jehož nitro právě prohlížíme. Příklad okna nahlížejícího do útrob instance třídy Obdelnik, je na obr. 1.17. Jak vidíte, tato třída má dva atributy třídy: prvním je krok, který definuje implicitní velikost posunu obdélníků, druhým je ibarva, o níž vám prozradím, že definuje implicitní barvu nových obdélníků. Poznámka: Ne všechny atributy (třídy i instancí) musí být nutně pro okolí třídy dostupné. K některým atributům může autor třídy definovat příslušné přístupové metody (getry a setry), jiné může nechat zevně nepřístupné a využívat je pouze pro vnitřní účely třídy a jejích instancí.
Instance třídy Obdelnik má podle očekávání 5 atributů instance: x-vou a y-vou pozici levého horního rohu, výšku a šířku obdélníku a jeho barvu. Hodnoty atributů popisují stav objektu. Mění-li se stav objektu (v našem případě mění-li se jeho poloha, velikost a/nebo barva), mění se i hodnoty jeho atributů. Nechte okno otevřené a zkuste požádat instanci, do jejíchž útrob nahlížíte, aby se někam posunula. Všimněte si, že při plnění tohoto příkazu se zároveň změní i hodnota příslušných atributů. Zkuste vyvolat další metody a přesvědčete se, jak ovlivňují hodnoty jednotlivých atributů. Nemusíme zůstat pouze u metod instancí. Stejným způsobem můžeme změnit i hodnoty atributu třídy. Otevřete okno prohlížeče objektů i pro jinou instanci téže třídy, zavolejte metodu setKrok(int), nastavte novou velikost kroku. V oknech prohlížeče objektů pak ověřte, že se hodnota příslušného atributu třídy změní u všech instancí dané třídy.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 25 z 27
1.9. Shrnutí – co jsme se v kapitole naučili
Strana 26 z 27
1.9 Shrnutí – co jsme se v kapitole naučili Nově zavedené termíny (abecedně) Tato kapitola byla nabitá novými termíny. Abyste si je mohli zopakovat, následuje seznam hypertextových odkazů na místa, kde jsem se o nich poprvé zmínil. Klepnutím na termín se přesunete do místa, kde byl termín zaveden. atributy instancí
JDK
rodičovská třída
atributy třídy
konstruktor
správce paměti
BlueJ
metoda
stav objektu
boolean
metoda třídy
String (typ)
členské proměnné
nadtřída
true
dceřinná třída
návratová hodnota
třída
diagram tříd
new (operátor)
typ
false
odvozená třída
UML
halda
objekt
vlastní instance
hlavička konstruktoru
objektově orientovaný program
vnitřní proměnné
hlavička metody identifikátor instance int (typ)
parametr
výstupní hodnota metody zpráva
podtřída projekt program
Důležité informace Shrňme si, co jsme se v kapitole dozvěděli: Třída popisuje společné vlastnosti jistého druhu objektů. Tyto objekty pak vystupují jako její instance. Mají-li některé z objektů zvláštní společné vlastnosti, bývá výhodné pro ně definovat zvláštní podtřídu, tzv. dceřinnou třídu. Původní třída je pak její rodičovskou třídou nebo nadtřídou. Objekt je vlastní instancí právě jedné třídy. Může však vystupovat jako instance kteréhokoliv z jejích rodičů. Objekty si mezi sebou mohou posílat zprávy. J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 26 z 27
1.9. Shrnutí – co jsme se v kapitole naučili
Strana 27 z 27
Objektově orientovaný program je v nějakém programovacím jazyce zapsaný popis použitých tříd, objektů a zpráv, které si tyto objekty posílají, doplněný u složitějších programů ještě o popis umístění programů na jednotlivých počítačích a jejich svěření do správy příslušných služebních programů. Nové objekty vytváříme prostřednictvím operátoru new a tzv. konstruktorů. Konstruktory jsou speciální metody zodpovědně za správné vytvoření instancí svých tříd. Zavoláním konstruktoru získáme odkaz na objekt. Program nikdy nepracuje s objektem, ale vždy pouze s odkazem na objekt. Zaslání zprávy objektu realizujeme zavoláním odpovídající metody. Vedle metod instancí existují i metody třídy, jejichž prostřednictvím zasíláme zprávu celé třídě. Metody mohou mít parametry. Metody se musí navzájem lišit svým jménem (identifikátorem) a/nebo seznamem typů parametrů. Metody mohou vracet hodnotu, a to i hodnotu objektového typu. Abychom mohli vracené hodnoty prohlédnout, otevře BlueJ po vykonání dané metody dialogové okno, v němž vracenou hodnotu zobrazí. Vrací-li metoda hodnotu objektového typu, můžeme v dialogovém okna klepnout na příslušný záznam a pak požádat buď o prohlédnutí dané instance nebo o předání odkazu na ni. Případný odkaz se uloží do zásobníku odkazů. Všechna data, která v programu vystupují, musí mít definovaný svůj typ. Odkazy, třídy, metody a další objekty, s nimiž v programu pracujeme, označujeme identifikátory. Identifikátory mohou obsahovat písmena (včetně písmen s diakritikou nebo např. japonských znaků), číslice a znaky „_“ (podtržítko) a „$“ (dolar). Nesmí začínat číslicí. V identifikátorech se rozlišují velká a malá písmena. Objekty si pamatují svůj stav prostřednictvím atributů. Vedle atributů instancí mohou být definovány i atributy třídy, které všechny instance dané třídy sdílí. Máme-li odkaz na instanci, můžeme BlueJ požádat o zobrazení jejích atributů a atributů její třídy.
Autor pracuje jako EDU expert ve firmě Amaio Technologies, Inc.
J01 Třídy a objekty.doc, verze 1.08.009, uloženo: středa 14.května.2003 – 15:41
Strana 27 z 27