Upozornění pro čtenáře a uživatele této knihy

Všechna práva vyhrazena. Žádná část této tištěné či elektronické knihy nesmí být reprodukována ani šířena v papírové, elektronické či jiné podobě bez předchozího písemného souhlasu nakladatele. Neoprávněné užití této knihy bude trestně stíháno.

Rudolf Pecinovský

Java 8

Úvod do objektové architektury pro mírně pokročilé

TIRÁŽ TIŠTĚNÉ PUBLIKACE:

Vydala Grada Publishing, a.s.

U Průhonu 22, 170 00 Praha 7

tel.: +420 234 264 401, fax: +420 234 264 400

www.grada.cz

jako svou 5670. publikaci

Odborní lektoři:

doc. Ing. Pavel Herout, Ph.D.,

doc. MUDr. Jiří Kofránek, CSc.,

doc. Ing. Vojtěch Merunka, Ph.D.,

doc. Ing. Miroslav Virius, CSc.

Odpovědný redaktor: Martin Vondráček, Ladislava Soukupová

Návrh vnitřního layoutu: Rudolf Pecinovský

Zlom: Rudolf Pecinovský

Počet stran 656

První vydání, Praha 2014

Vytiskly Tiskárny Havlíčkův Brod, a.s.

V knize použité názvy mohou být ochrannými známkami nebo registrovanými ochrannými známkami příslušných vlastníků.

Copyright © Grada Publishing, a.s., 2014

Cover Photo © fotobanka Allphoto.cz

ISBN 978-80-247-4638-8

ELEKTRONICKÉ PUBLIKACE:

ISBN 978-80-247-9480-8 ve formátu PDF

ISBN 978-80-247-9481-5 ve formátu EPUB

Skrytí spoluautoři

Při tvorbě takto rozsáhlé knihy se autor nemůže spolehnout pouze sám na sebe. Je známou věcí, že když po sobě autor čte svůj rukopis, čte velmi často to, co chtěl napsat, a ne to, co doopravdy napsal. S kontrolou jazykových chyb mu může pomoci redaktor a jazykový korektor. S kontrolou odborných zaškobrtnutí mu však musí pomoci někdo jiný.

S kontrolou odborné správnosti musí pomoci někdo, kdo je odborně na výši a odhalí, že se autor vyjadřuje nepřesně nebo dokonce chybně. S kontrolou srozumitelnosti výkladu musí zase pomoci někdo, kdo se chce látku naučit a je ochoten text podrobně pročíst a upozorňovat na místa, kde výkladu zcela nerozumí nebo se mu zdá, že by bylo vhodné ještě něco doplnit. Úplně dokonalé pak je, když váš text čte zkušený učitel, který umí odhalit nejenom oba výše popsané druhy nepřesností či dokonce chyb, ale také naznačit možná potenciální nedorozumění a dezinterpretace vzniklá z podobnosti vykládané látky s jinými oblastmi, o nichž se výklad nezmiňuje.

Měl jsem to štěstí, že se mi podařilo získat spolupracovníky (a tím i kritiky) ze všech tří zmiňovaných skupin. Všem bych jim chtěl tímto poděkovat. Řekl bych, že díky jejich připomínkám a doporučením je výsledný text kvalitnější.

Všechny tyto dobrovolné spolupracovníky vnímám jako spoluautory. Proto mi dovolte, abych je tu alespoň abecedně vyjmenoval – byli to: Milan Augustin, Tibor Bako, Jakub Hadam, Michael Charvát, Jiří Kofránek, Jiří Kubala, Petr Kuchař, David Král, Filip Malý, Nikolas Patrik, Jarmila Pavlíčková, Luboš Pavlíček, Josef Svoboda, Petr Vidrman, Martin Vondráček a Martin Žamberský.

Úvod

Otevíráte knížku, která vás chce naučit programovat moderním, objektově orientovaným stylem. Stylem, jímž se v dnešní době vyvíjí drtivá většina klíčových aplikací, ale k jehož výuce ještě řada škol nedospěla. Po nastudování této knížky budou proto mnozí z vás vědět o moderním programování víc než leckterý z vašich učitelů.

Komu je kniha určena

Kniha je určena programátorům, kteří potřebují získat hlubší vhled do problematiky objektově orientovaného programování a návrhu architektury objektově orientovaných programů. K jejímu studiu přitom nepotřebují žádné velké předběžné zkušenosti. Stačí znalosti na úrovni mých začátečnických učebnic.

Kniha je reakcí na nepřetržité nářky vedoucích programátorských týmů, kteří posílají nastoupivší absolventy do mých přeškolovacích kurzů. Stěžují si, že školy opouštějí možná skvělí kodéři, ale neschopní architekti, že tito absolventi znají několik programovacích jazyků a řadu užitečných frameworků, ale mají problém s návrhem kvalitní architektury zadávaného programu.

Většina škol, učebnic a výukových kurzů se soustředí především na výklad syntaxe probíraného programovacího jazyka a probrání hlavních knihoven používané platformy. Jejich autoři se soustřeďují na detaily v bláhové naději, že jejich studenti a čtenáři pak v průběhu následující praxe pochopí vyšší principy. Když se ve výukovém programu objeví kurzy návrhových vzorů, končí často jako defilé technik, jak to či ono šikovně zakódovat.

Koncepce knihy

Ve svých knihách se pokouším tento stereotyp změnit. Soustředím se především na předvádění toho, jak program navrhnout a probrat věci, které považuji za důležité a přitom je v jiných učebnicích většinou nenajdete. Přitom se pokouším vše demonstrovat na příkladech. Na rozdíl od některých učebnic se však nechci omezovat pouze na AHA-příklady, jejichž jediným cílem je, aby po jejich prostudování student prohlásil „Aha! Takto to funguje!“, i když se jim v některých chvílích nevyhnu. Snažím se ale co největší část látky demonstrovat na složitějších příkladech, které však nejsou zahlceny spoustou šumu, za který považuji kód, který se musí naprogramovat, i když s vykládanou látkou přímo nesouvisí. Dávám přitom přednost příkladům používajícím grafiku, protože jsou pro daný účel většinou nejnázornější.

Kniha je koncipována jako druhý díl knihy Java 7 – Učebnice objektové architektury pro začátečníky[1]. Předpokládá proto, že znáte látku zhruba na úrovni prvního dílu. Protože ale očekávám, že knihu bude číst i řada čtenářů, kteří získali své první programátorské zkušenosti z jiných zdrojů, tak pro jistotu na počátku nejdůležitější věci velice stručně zopakuji.

Co se naučíte, uspořádání knihy

Snažil jsem se v knize soustředit na oblasti, které se do jiných knih nevešly, a přitom je jejich osvojení velmi důležité, protože jejich neznalost je v lepším případě příčinou těžkopádných řešení a v horším případě příčinou špatně odhalitelných chyb.

V první části nejprve bleskově zopakuji základní látku prvního dílu a pak vás seznámím s jedním ze tří nejpoužívanějších profesionálních vývojových prostředí: s prostředím NetBeans. V minulém dílu jsme pracovali s vývojovým prostředím BlueJ. To je sice asi nejlepší prostředí pro získání základních představ a návyků objektově orientovaného programování, ale pro profesionální práci se příliš nehodí. Protože je ale zvládnutí vývojového prostředí zhruba stejně náročné jako zvládnutí programovacího jazyka, je mu věnován celý zbytek první části. Naučíte se je konfigurovat, vytvářet v něm projekty a využívat jeho výhodných vlastností pro zefektivnění své práce.

V druhé části si postupně ukážeme různé programové konstrukce a postupy, které můžete využít při návrhu architektury projektu. Postupně se seznámíte s dalšími návrhovými vzory, osvojíte si definici interfejsů obsahujících definice metod včetně jejich implementace, dozvíte se o možnosti parametrizace datových typů a jejich vzájemném vnořování, naučíte se používat lambda-výrazy, které umožňují pracovat s částmi kódu jako s proměnnými, a získáte první zkušenosti s prací s kontejnery a datovody.

Ve třetí části se ponoříme do výkladu dědění implementace. Začneme podrobným výkladem zavádění objektů a tříd a budeme pokračovat základními vlastnostmi dědění implementace. Dozvíte se, jak vytvářet třídy, jejichž předky jsou jiné třídy, a hlavně na co si dát při konstrukci takovýchto tříd pozor. Pokusím se vám demonstrovat některé vlastnosti dědění na třídách, které dědění emulují využitím návrhového vzoru Dekorátor a předvedu vám, jak definovat společného rodiče skupině tříd, které mají některé společné vlastnosti.

Ve čtvrté, závěrečné části, vám představím algoritmické konstrukce, jejichž používání je sice postupně nahrazováno jinými technikami (ty probírají předchozí části učebnice), ale prozatím se bez nich stále ještě neobejdeme. Navíc se ve starších programech s některými novějšími konstrukcemi ani nesetkáte.

Programovací jazyk

Přestože má kniha ve svém názvu uveden jazyk Java, tak musím dopředu oznámit, že se nejedná o učebnici jazyka Java. Těch je k dispozici více než dost. Jedná se o učebnici objektově orientovaného programování a jazyk Java je zde používán jako jazyk, v němž jsou zapsány programy demonstrující probíranou látku. Tento jazyk jsem zvolil z několika důvodů:

Je to stále s odstupem nejpoužívanější objektově orientovaný jazyk. Programátoři v Javě jsou stále nejžádanější (a mají i jedny z nejvyšších platů).

Je to jazyk poskytující všechny klíčové konstrukce používané v moderním programování.

Vytvořené programy nejsou omezeny na jediný operační systém, ale můžete je přenášet mezi různými operačními systémy.

A vlastnost neocenitelná pro studium a začátečnické experimenty: nástroje pro vývoj všech druhů aplikací od čipových karet až po rozsáhlé aplikace běžící na několika počítačích můžete sehnat zdarma.

Potřebné vybavení

Pro úspěšné studium této knihy budete potřebovat:

chuť naučit se objektově programovat a výdrž v situacích, kdy se vám nebude zcela dařit,

rozumně výkonný počítač,

základní vývojovou sadu Javy (JDK) ve verzi 8 a vyšší, kterou si můžete stáhnout se stránek http://www.oracle.com/technetwork/java/javase/downloads.

vývojové prostředí NetBeans ve verzi 8 a vyšší, které si můžete stáhnout ze stránek https://netbeans.org.

doprovodné příklady, které si můžete stáhnout ze stránky knihy http://knihy.pecinovsky.cz/uoa2_j8.

Doprovodné projekty

Na stránce knihy na adrese http://knihy.pecinovsky.cz/uoa2_j8 najdete také soubor s generátorem projektů použitých v knize. Téměř každá kapitola má svůj doprovodný projekt. Některé kapitoly jich mají dokonce několik. Možná bude někomu připadat zbytečné vytváření takového množství projektů, když jsou jednotlivé sekce umísťovány do samostatných balíčků a řada projektů ve svém obsahu vychází z projektů předchozích, k nimž buď něco přidá a/nebo něco jiného drobně upraví. Důvodem tohoto uspořádání je snaha vyjít začátečníkům vstříc a umožnit jim v každé kapitole začít znovu s funkčním projektem nezávisle na tom, do jakého stavu přivedli projekt z kapitoly přechozí.

První díl byl určen pro naprosté začátečníky, kterým jsem se snažil vyjít vstříc, a protože vím, jaký problém s angličtinou má značná část studentů, používal jsem pro větší názornost české identifikátory. Pořízením této učebnice jste se přihlásili mezi pokročilejší programátory, a ti se bez znalosti angličtiny neobejdou. V této branži platí: programátor musí umět anglicky, anebo musí změnit zaměstnání. V tomto dílu jsou proto už všechny identifikátory anglicky. České zůstávají pouze dokumentační komentáře.

Doplňková literatura

Kniha je tlustá, ale ani tak se do ní nevešlo vše, co by bylo potřeba. Navíc se mi nechtělo podrobně rozebírat témata, která už jsem vysvětlil v publikaci, kterou si můžete zdarma stáhnout. Hovořím konkrétně o knize Java 5.0 – Novinky jazyka a upgrade aplikací, kterou si můžete zdarma stáhnout na mých webových stránkách na adrese http://knihy.pecinovsky.cz/java5novinky.

Kromě toho se na svých stránkách http://vyuka.pecinovsky.cz chystám postupně zveřejňovat materiály, které budu připravovat pro studenty a případné polotovary budoucích publikací. Když si uvědomím, že při psaní knih vychází honorář asi tak na 7 korun za hodinu práce, tak se domnívám, že nic neztratím, když budu budoucí texty poskytovat zdarma a ponechám na rozhodnutí čtenářů, zda si jich cení tak, že jsou za ně ochotni něco zaplatit.

Použité konvence

Místní nabídka

„Skrytí spoluautoři“, kteří četli vytvářený rukopis, mne upozornili na některé formulace, které je nebo jejich kolegy trochu zaskočily. Jednou z nich je termín místní nabídka, který se sice v počítačové literatuře používá od počátku devadesátých let, nicméně do programátorského slangu ještě nepronikl.

Opatrně proto připomenu, že budu-li někde hovořit o tom, že máte zadat nějaký příkaz v místní nabídce objektu Xyz, znamená to, že máte na tento objekt najet myší, stisknutím pravého tlačítka rozbalit jeho místní nabídku (anglicky context menu) a v ní zadat požadovaný příkaz.

Formátování

K tomu, abyste se v textu lépe vyznali a také abyste si vykládanou látku lépe zapamatovali, používám několik prostředků pro odlišení a zvýraznění textu.

Objekty První výskyt nějakého termínu a další texty, které chci zvýraznit, vysazuji tučně.

Názvy Názvy firem a jejich produktů vysazuji kurzivou. Kurzivou vysazuji také názvy kapitol, podkapitol a oddílů, na které se v textu odkazuji.

Citace Texty, které si můžete přečíst na displeji, např. názvy polí v dialogových oknech či názvy příkazů v nabídkách, vysazuji tučným bezpatkovým písmem.

Adresy Názvy souborů a internetové adresy vysazuji obyčejným bezpatkovým písmem.

Program Texty programů a jejich částí vysazuji neproporcionálním písmem.

Kromě částí textu, které považuji za důležité zvýraznit nebo alespoň odlišit od okolního textu, najdete v textu ještě řadu doplňujících poznámek a vysvětlivek. Všechny budou v jednotném rámečku, který bude označen ikonou charakterizující druh informace, kterou vám chce poznámka či vysvětlivka předat.

Symbol jin-jang bude uvozovat poznámky, s nimiž se setkáte na počátku každé kapitoly. Zde vám vždy prozradím, co se v dané kapitole naučíte.

Otevřená schránka s dopisy označuje informace o projektu, s nímž budeme v dalším textu pracovat, nebo v něm najdete vzorové řešení.

Obrázek knihy označuje poznámku týkající se používané terminologie. Tato poznámka většinou upozorňuje na další používané termíny označující stejnou skutečnost nebo na konvence, které se k probírané problematice vztahují. Seznam všech terminologických poznámek najdete v rejstříku pod heslem „terminologie“.

Obrázek počítače označuje zadání úkolu, který máte samostatně vypracovat. Seznam všech úloh najdete v rejstříku pod heslem „úloha“.

Píšící ruka označuje obyčejnou poznámku, která pouze doplňuje informace z hlavního proudu výkladu o nějakou zajímavost.

Ruka s hrozícím prstem upozorňuje na věci, které byste měli určitě vědět a na které byste si měli dát pozor, protože jejich zanedbání vás většinou dostane do problémů.

Usměváček vás bude upozorňovat na různé tipy, kterými můžete vylepšit svůj program nebo zefektivnit svoji práci.

Mračoun vás naopak bude upozorňovat na různá úskalí programovacího jazyka nebo programů, s nimiž budeme pracovat, a bude vám radit, jak se těmto nástrahám vyhnout či jak to zařídit, aby vám alespoň pokud možno nevadily.

Brýle označují tzv. „poznámky pro šťouraly“, v nichž se vás snažím seznámit s některými zajímavými vlastnostmi probírané konstrukce nebo upozorňuji na některé souvislosti, jejichž znalost však není k pochopení látky nezbytná.

Symbol znamení raka označuje poznámku popisující doprovodnou animaci (animovaný výklad), která se vás bude snažit naučit nějakou dovednost, která se špatně popisuje slovy.

Odbočka

Občas je potřeba vysvětlit něco, co nezapadá přímo do okolního textu. V takových případech používám podšeděný blok se silnou čarou po straně. Tento podšeděný blok je takovou drobnou odbočkou od ostatního výkladu. Nadpis podšeděného bloku pak najdete i v podrobném obsahu mezi nečíslovanými nadpisy.

1 Kniha je současně slibovaným druhým dílem starší učebnice OOP – Naučte se myslet a programovat objektově. Ta sice vyšla v jiném nakladatelství, ale protože dané nakladatelství nedokázalo před několikeré upomínky dostát svým závazkům, tak jsem z tvorby druhého dílu vycouval.

Část I:

Vývojové prostředí

Tato část vám nejprve připomene, co byste měli znát, abyste mohli bez problémů pokračovat ve čtení knihy. Pak vás postupně seznámí s vývojovým prostředím NetBeans a jeho základními vlastnostmi, které by vám mohly pomoci výrazně zefektivnit vývoj programů.

Kapitola 1

Co byste měli znát z prvního dílu

Co se v kapitole naučíte

V této kapitole si velmi stručně připomeneme, co jste se naučili v prvním dílu učebnice, a seznámím vás s několika termíny, které budeme v dalším textu používat.

1.1Přehled látky prvního dílu

V první verzi rukopisu této knihy jsem z minulého dílu převzal podkapitoly nazvané Shrnutí – co jsme se naučili, v nichž jsem na konci každé kapitoly vždy stručně vyjmenoval, co se v dané lekci probíralo. Přitom jsem s údivem zjistil, že tento velmi zhuštěný přehled má přes 30 stránek. To mne zaskočilo. I když jsem jej prošel a vyjmul vše, co se týkalo jen BlueJ a projektů vytvářených v prvním dílu, stále mi ještě připadal na úvodní kapitolu příliš velký.

Rozhodl jsem se proto, že původní text úvodní kapitoly vyjmu z učebnice, nepatrně jej upravím a vystavím v samostatném souboru na webových stránkách knihy, odkud si jej budou moci stáhnout a přečíst i ti, kteří první díl nečetli a rozhodli se začít rovnou tímto druhým dílem (zmíněný text najdete na stránce knihy). V dalším textu budu předpokládat, že vše, co je v onom stručném shrnutí uvedeno, již znáte a mohu na to plynule navázat.

Pro jistotu ale ještě v následujících pasážích připomenu některé klíčové termíny, které jsem v prvním dílu zavedl a které nemusí být zcela srozumitelné těm, kteří získávali prvotní informace z jiných zdrojů než z prvního dílu. Zkušenost totiž ukazuje, že řada studentů tyto termíny zaměňuje, směšuje a/nebo je špatně interpretuje. Stručný přehled klíčových termínů uvádím především proto, abyste v okamžiku, kdy narazíte na daný termín v textu, věděli, o čem hovořím.

1.2Definice × deklarace

Než začneme s vlastním opakováním, chtěl bych připomenout dva obecné jazykové termíny, které si studenti občas pletou, a to termíny deklarace a definice:

Deklarace je část kódu, v níž předem oznamujeme některé vlastnosti vytvářeného programu. Je to takové prohlášení. Účelem deklarace je poskytnout překladači informace, na jejichž základě pak může kontrolovat, jestli ve svém programu neděláte nějaké evidentní chyby.

Definice je část kódu, v níž něco doopravdy vytváříme. Jedná-li se o metodu, opravdu se někde objeví předpis definující, jak metoda pracuje. Jedná-li se o objekt, necháváme mu přidělit paměť a přiřadit počáteční hodnotu.

U datových objektů (proměnných a konstant) se často slučuje deklarace s definicí. Danou proměnnou deklarujeme (prozradíme, jaký bude mít datový typ a jak se bude jmenovat) a současně ji i definujeme (přiřadíme jí počáteční hodnotu, čímž donutíme překladač, aby pro ni vyhradil potřebnou paměť).

Klasické abstraktní metody, s nimiž se setkáme v interfejsech, jsou zde pouze deklarovány. V deklaraci pouze překladači vysvětlujeme, jakou by měla mít požadovaná metoda signaturu, jaká by měla být, kdyby ji někdo definoval.

Ve třídách jsme pak metody přímo definovali, protože jsme za hlavičkou metody zapisovali její tělo, v němž jsme popisovali, co má daná metoda dělat.

V tomto dílu se dozvíte, že situace není tak jednoduchá, jak se původně zdálo, tj. že se v interfejsech metody deklarovaly a ve třídách definovaly. Dozvíte se, že ve třídě můžete deklarovat abstraktní metodu a naopak v interfejsu definovat konkrétní metodu. K tomu všemu postupně dojdeme.

1.3Co je to objekt

Vraťme se ale k objektovému programování. Říkali jsme si, že každý program je simulací reálného nebo virtuálního světa. Tento svět je tvořen objekty, které jsou v programu reprezentovány stejně pojmenovanými daty. Jako objekt označujeme v programu kolekci dat reprezentující odpovídající objekt z onoho simulovaného světa.

Oproti běžnému chápání objektů v reálném světě je však v programu používán termín objekt mnohem obecněji: objekty v programu mohou reprezentovat cokoliv, co můžeme pojmenovat, tj. cokoliv, co můžeme označit podstatným jménem.

V programu proto chápeme jako objekty i vlastnosti (velikost, směr, krása), děje (připojení, přerušení, výpočet) a další pojmenovatelné entity. Objektem je proto i třída, rozhraní, metoda atd.

Malá poznámka pro ty, kteří mají zkušenosti s jazyky Turbo Pacal a Delphi. Jejich autor nám přichystal malý terminologický guláš, protože to, co zbytek světa označuje termínem třída, začal nazývat objekt. Možná proto budete chvíli zmateni, ale věřím, že jenom chvíli.

1.4Datový typ, třída, class-objekt

V programech se vyskytují celé skupiny objektů, které mají stejnou charakteristiku. Tuto charakteristiku označujeme jako datový typ oněch objektů. Objekty s charakteristikou definovanou nějakým datovým typem označujeme jako instance daného datového typu.

Datové typy lze rozdělit do několika skupin. Jazyk Java rozlišuje následující druhy datových typů:

Primitivní datové typy představují typy, které nejsou objektové (nemají své instance), ale zato mají přímou podporu v instrukčním souboru většiny procesorů. Nabourávají čistou objektovou orientovanost jazyka a byly do něj zavedeny pro zvýšení efektivity. Prozatím se bez nich neobejdeme, ale to by se mělo v některé z příštích verzí změnit.

Třídy představují základní druh objektového datového typu.

Výčtové typy jsou speciální třídy, které mají pouze předem definované instance, přičemž tuto množinu instancí není možno dále měnit.

Interfejsy představují datové typy reprezentující rozhraní instancí tříd, které tyto interfejsy implementují (podrobněji za chvíli).

Datové typy jsou zvláštním druhem objektů. V jazyce Java nejsou (na rozdíl např. od jazyka Smalltalk) instancí žádného datového typu. Můžeme je však oslovovat prostřednictvím speciálních zástupných objektů, které jsou instancemi třídy java.lang.Class (podrobněji se s nimi seznámíme v pasáži Třídy jako objekty – class-objekt třídy).

1.5Zpráva × metoda, polymorfismus

Objekty simulovaného světa spolu navzájem komunikují – fyzikálně, chemicky, biologicky, verbálně, společensky atd. Veškeré tyto interakce reprezentujeme v programu jako zasílání zpráv jednoho objektu jinému.

ZprávaTermínem zpráva označujeme požadavek, který zasílá jeden objekt druhému. Odesílatel zprávy přitom očekává od adresáta reakci odpovídající kontraktu dané zprávy (co je to kontrakt, si připomeneme za chvíli).

MetodaTermínem metoda označujeme kód definující, jak bude daný objekt reagovat na zaslanou zprávu.

Každá zpráva, na kterou umí objekt zareagovat, má přiřazenu metodu, v níž je definována požadovaná reakce objektu na zaslání dané zprávy. Některým zprávám ale může být přiřazeno více metod a to, která metoda se použije, záleží na různých věcech. Většina jazyků (a Java mezi nimi) odvozuje to, jaká metoda bude použita, od typu osloveného objektu; obecně to ale může záviset i na jiných věcech.

Schopnost objektů reagovat na stejnou zprávu různě označujeme jako polymorfismus. Takové chování ale pouze reprezentuje stav v onom světě simulovaném naším programem. Představte si např. nějaký sportovní zápas. Všichni v hledišti jsou instance typu Člověk. Nicméně na zprávu o vstřeleném gólu budou instance podtypu FanoušekTýmuA reagovat jinak než instance podtypu FanoušekTýmuB a opět jinak budou reagovat instance podtypu ProdavačkaNaTribuně.

1.6Rozhraní × interfejs

Pro ty, kteří nečetli minulý díl, bych připomněl, že v textu učebnice rozlišuji mezi termíny rozhraní a interfejs:

Rozhraní představuje množinu charakteristik, jimiž se daná entita (balíček, třída, metoda, atribut, …) prezentuje svému okolí, a které tím pádem okolí o dané entitě explicitně zná. Své rozhraní má každá entita programu.

Interfejs je programová konstrukce, kterou Java zavedla a kterou od ní mnohé další programovací jazyky převzaly. Díky interfejsu můžeme specifikovat požadavky na rozhraní objektů, s nimiž se chystáme pracovat.

Některé programátory irituje, že používám počeštěnou podobu anglického interface. V tištěném textu však musíme dávat přednost spisovným tvarům před slangovými. Převzaté slovo interface nelze skloňovat, a proto dávám přednost povolenému (viz Akademický slovník cizích slov. Academia Praha 1995. ISBN 80-200-0497-1) počeštěnému tvaru. Ostatně počeštění tvaru často používaných převzatých slov je běžné – podívejte se např. na slova fotbal, hokej či tenis.

V minulém dílu jsem navíc využil toho, že interfejs sloužil opravdu jenom k popisu požadovaného rozhraní, a pokud jsem se domníval, že nemůže dojít k nedorozumění, používal jsem český termín rozhraní i při označování dané programové konstrukce. To už si v tomto dílu nemohu dovolit, protože v Javě 8 přestal interfejs pouze deklarovat požadované rozhraní. Java 8 totiž umožňuje, abychom v interfejsu definovali i doporučenou implementaci (viz kapitolu 14 Implicitní implementace – RingVehicle, ControlledVehicle), a navíc může obsahovat i definice statických metod. Protože se nyní významy obou termínů vzdálily, budu jejich terminologické rozdělení důsledně dodržovat.

V souvislosti s rozhraním bych ještě připomněl další dva termíny: signatura a kontrakt:

Signatura označuje tu část rozhraní, kterou může zkontrolovat překladač. Sem patří např. název dané entity, její datový typ (případně typ metod návratové hodnoty), u metod typy jednotlivých parametrů a některé další překladačem kontrolovatelné charakteristiky.

Kontrakt označuje tu část rozhraní, kterou překladač zkontrolovat nedokáže – např. že šířka obdélníku nesmí být záporná. Kontrakt popisujeme v dokumentačních komentářích a za jeho dodržení je zodpovědný programátor. Za prvé tak, že sám kontrakty dodržuje, a za druhé tak, že za běhu programu kontroluje, že je dodržují i používané objekty (s jednou ověřovací konstrukcí se seznámíme v podkapitole 9.15 Ověřování podmínek – příkaz assert).

1.7Zapouzdření a skrývání implementace

Vedle rozhraní má každá entita programu svoji implementaci, která specifikuje, jak daná entita dosahuje funkčnosti deklarované v jejím rozhraní. Jedna z hlavních zásad správného programování doporučuje programovat tak, abyste v každé situaci využívali pouze znalostí rozhraní používané entity a nesnažili se vylepšit program díky znalostem její implementace.

Zásada se nejlépe dodržuje tak, že nemám šanci ji porušit. Proto moderní programovací jazyky umožňují maximálně skrývat implementační detaily.

V souvislosti se skrýváním implementace se často hovoří o zapouzdření. Tímto termínem byla původně označována skutečnost, že objektové programování zapouzdřuje do společného objektu data i kód, který s těmito daty pracuje. Postupem času původní význam termínu zapouzdření ustupoval do pozadí a stále častěji se tímto termínem označovalo především skrývání implementace. Podvolím se tomuto všeobecnému trendu a budu jej v tomto významu používat i v této učebnici.

1.8Datové typy a jejich dědění

V minulém dílu jsme se seznámili s konstrukcí dědění datových typů. Vysvětlili jsme si, že datový typ potomka specifikuje společné vlastnosti nějaké speciální podmnožiny instancí předka, přičemž objekty z této podmnožiny mají oproti ostatním instancím předka jisté speciální vlastnosti, kvůli nimž je pro ně vhodné definovat samostatný datový typ. Současně jsem vám prozradil, že existují tři typy dědění:

Přirozené (nativní) dědění hovoří o tom, jak specializaci objektů cítíme bez ohledu na to, jak ji naprogramujeme.

Ve škole jsme se např. učili, že čtverec je speciální případ obdélníku. Vysvětlovali jsme si, kdy můžeme tuto obecnou znalost promítnout do našeho programu, a kdy si to naopak dovolit nemůžeme.

Dědění typu odpovídá v programech dědění rozhraní. Toto dědění se uplatňuje nejen při dědění interfejsů, ale i při implementaci interfejsu třídou. Z hlediska dědění typů lze proto implementovaný interfejs považovat za jednoho z rodičů tříd, které jej implementují.

Připomínám, že dědění typů je o slibech. Když datový typ prohlásí, že dědí nějaký jiný typ, tak překladač může zkontrolovat pouze to, jestli dodržuje požadovanou signaturu. Na zodpovědnosti programátora pak je, aby vedle signatury dodržel i kontrakt, a splnil tak slib, který dal, když přihlašoval datový typ k dědění jeho rodiče. Nedodržení tohoto slibu je příčinou celé řady chyb.

Dědění implementace se uplatní při dědění tříd. Při něm třída od svého rodiče přebírá nejenom jeho rozhraní, ale překladač zabezpečí, že přebere také veškerou jeho implementaci. Nemusí tedy definovat pro všechno vlastní metody, ale v řadě případů může použít metodu zděděnou od svého rodiče či od některého z prarodičů.

V dědění implementace jsou skryty mnohé záludnosti (na některé z nich jsem v minulém dílu upozorňoval), a proto jsem jeho výklad odložil až do tohoto dílu. Budeme o něm hovořit ve třetí části, kdy budete mít větší zkušenosti, které vám za prvé pomohou:

odhalit situace, v nichž je použití dědění implementace nešikovné či přímo nevhodné (velmi oblíbená chyba, kterou dělají mnozí zdánlivě zkušení programátoři),

orientovat se v situacích, kdy je použití dědění implementace výhodné, ale hrozí při něm riziko zanesení „oblíbených“ chyb.

Má-li být náš program stabilní a v budoucnu snadno rozšiřitelný, musíme při dědění vždy respektovat všechny tři aspekty.

Vlastní instance třídy a mateřská třída objektu

Abych usnadnil orientaci v příslušnosti objektu k datovým typům, zavedl jsem ještě další dva termíny:

Vlastní instance třídy (anglicky class‘ own instance) je instance, kterou „porodila“ daná třída, a není proto instancí žádného z jejích potomků.

Mateřská třída objektu (anglicky home class). Je-li objekt vlastní instancí nějaké třídy, označujeme tuto třídu jako mateřskou třídu daného objektu.

LSP – Liskov Substitution Principle

Před chvílí jsem říkal, že odvozený typ specifikuje společné vlastnosti podmnožiny instancí předka. Z vlastnosti, že prvky podmnožiny nepřestávají být prvky původní množiny, vyplývá, že instance potomků nepřestávají být instancemi předka, a měly by proto být schopny kdykoliv vystupovat v roli instance kteréhokoliv ze svých předků.

Zásadu, že potomek musí být schopen kdykoliv plnohodnotně vystupovat v roli instance předka, formulovala v roce 1987 ve své přednášce[2] Barbora Liskov a od té doby je označována jako Liskov Substitution Principle (Substituční princip Liskové) a používá se pro ni zkratka LSP.

Bohužel, řada programátorů tuto zásadu ve svých programech porušuje, a pak se diví, proč jim jejich „dokonalé programy“ nechodí. S příklady porušujícími tuto zásadu se bohužel setkáte i v přednáškách řady universit (včetně těch nejprestižnějších) o učebnicích a kurzech programování ani nemluvě.

Přetěžování × přebíjení × zakrývání metod

V souvislosti s děděním bych připomněl další tři termíny, které si začátečníci občas pletou, a to přetěžování, přebíjení a zakrývání metod.

O přetěžování (anglicky overloading) metod hovoříme tehdy, definuje-li jeden datový typ několik metod se stejným názvem, ale rozdílnou signaturou.

O přebíjení (anglicky overriding) nebo překrývání metod hovoříme tehdy, definuje-li potomek metodu se stejnou signaturou, jako má některá z viditelných metod rodiče. Potomkova verze metody je přitom začleněna do definice objektu tak, aby se použila pokaždé, když potomkovi někdo pošle příslušnou zprávu, a to nezávisle na tom, za instanci jakého typu se v danou chvíli potomek vydává. Přebíjení se budeme podrobněji věnovat v kapitole 24 Virtuální metody a jejich přebíjení.

O zakrývání (anglicky hiding) metod hovoříme tehdy, pokud potomek definuje metodu se stejnou signaturou, jako má některá z metod jeho rodiče, avšak rodičovská metoda zůstává dostupná a to, která z metod se použije, záleží na tom, komu se daná zpráva posílá. V Javě je možno zakrývat pouze statické metody. Instanční metody je možné pouze přetížit či přebít. Zakrývání se budeme podrobněji věnovat v kapitole 23 Zakrývání atributů a metod.

Překlad přebít přesněji odpovídá anglickému originálu, a proto mu budu dávat přednost. V minulém dílu jsem si to ještě netroufl a dal na námitky kolegů, že takový termín je příliš lidový a do odborné terminologie nepatří. Pak jsem si ale řekl, že nemusíme být tak úzkoprsí. Když mohou být lidové výrazy v angličtině, proč bychom je nemohli mít v češtině. Angličan či Američan klidně označí programový modul termínem podniková fazole (enterprise bean). Našim programátorům z takového označení naskakuje kopřivka. Pokud máte s takovýmito termíny mentální problémy, doporučuji vám počkat si na vydání anglické verze této učebnice. Tam budu sice používat tytéž výrazy, ale v anglickém textu takovéto termíny nikoho neuráží.

Konec ukázky

Table of Contents

Skrytí spoluautoři

Úvod

Komu je kniha určena

Koncepce knihy

Co se naučíte, uspořádání knihy

Programovací jazyk

Potřebné vybavení

Doprovodné projekty

Doplňková literatura

Místní nabídka

Formátování

Část I: Vývojové prostředí

Kapitola 1 Co byste měli znát z prvního dílu

1.1 Přehled látky prvního dílu

1.2 Definice × deklarace

1.3 Co je to objekt

1.4 Datový typ, třída, class-objekt

1.5 Zpráva × metoda, polymorfismus

1.6 Rozhraní × interfejs

1.7 Zapouzdření a skrývání implementace

1.8 Datové typy a jejich dědění

Vlastní instance třídy a mateřská třída objektu

LSP – Liskov Substitution Principle

Přetěžování × přebíjení × zakrývání metod

1.9 Odkazové a hodnotové datové typy

1.10 Návrhové vzory

1.11 Modul × komponenta × knihovna × framework

Modul

Komponenta

Knihovna

Framework

1.12 Změny šablon

1.13 Knihovna CanvasManager

1.14 Shrnutí – co jsme se naučili

Kapitola 2 Vývojové prostředí NetBeans

2.1 Instalace

2.3 Aplikační okno, panely a karty

2.8 Editor – nastavení editoru

Karta General

Karta Code Completion

2.9 Fonts & Colors – nastavení písma a barev

2.12 Team

2.13 Appearance – nastavení vzhledu

2.14 Miscellaneous – zbylá nastavení

2.16 Export a import nastavení

Kapitola 3 Projekty v NetBeans – Library

3.5 Práce s balíčky

Přesun tříd mezi balíčky

3.7 Programátorská dokumentace (API)

3.9 Vlastnosti projektu

Kapitola 4 Vytváříme nový projekt – AHA

Kapitola 5 Práce na připraveném projektu – Elevator

5.3 Analýza problému

5.6 Testovací třída

Inicializace a finalizace bloku testů v dané třídě

5.7 Definice vlastní třídy

Kapitola 6 Spolupráce projektů – Vehicle

6.2 Vytvoření nové třídy

6.4 Použití frameworku či knihovny

6.5 Oprava špatného nastavení

6.7 Konstruktory

Kapitola 7 Testovací třída – VehicleTest, Robot

7.2 Obsah testovací třídy

7.3 Šablona testovací třídy

7.4 Využití služeb třídy IndentingReporter

7.5 Spuštění testů

7.6 Definice inicializačních a finalizačních metod

7.8 Vytvoření požadovaných testů

Kapitola 8 Ladění programů – Robot

8.1 Metody ladění

8.6 Zarážka na entitě

Kapitola 9 Program ve výjimečné situaci

9.5 Co výjimky umí

9.7 Zachycení vyhozené výjimky

9.8 Několik současně odchytávaných výjimek

9.10 Testování správného vyhození výjimky

Kapitola 10 Návrhový vzor Tovární metoda

10.5 Použití tovární třídy v projektu s vozidly

10.6 Možnost výběru testované třídy

Kapitola 11 Návrhový vzor Stav – Robot4

Kapitola 12 Návrhový vzor Stavitel – RingBuilder

12.3 Definice segmentů

12.5 Definice dopravního okruhu

Správa vytvořeného okruhu

12.7 Definice stavitele – RingBuilder

12.10 Dokončení definice okruhu

Kapitola 13 Návrhový vzor Dekorátor – SmoothVehicle

13.3 Definice dekorující třídy

Kapitola 14 Implicitní implementace – RingVehicle, ControlledVehicle

14.11 Rozšíření interfejsu IVehicleFactory

Kapitola 15 Generické datové typy a metody

15.6 Varování překladače a jejich potlačení

Kapitola 16 Pokročilejší práce s typovými parametry

16.7 Definice parametrizovaného datového typu

Kapitola 17 Funkční interfejsy a lambda-výrazy

17.5 Předčasné zhasínání

17.7 Světlo umožňující ovlivnit tvar žárovky

17.8 Generická verze třídy – třída LightG <B extends IChangeable & IColorable>

Kapitola 18 Rekurzivní volání

18.4 Pojezdy tam zpět – metoda zigZag

Kapitola 19 Interní datové typy

19.4 Použití

19.7 Pomocná vnořená přepravka

19.8 Vnořená tovární třída

19.9 Vnitřní třídy

19.10 Lokální třídy

Kapitola 20 Kontejnery a datovody

20.1 Kontejnery

20.3 Datovody (streams)

20.5 Použití datovodu – blikající světla

20.10 Složitější příklad

20.11 Konverze prvků v datovodu

Kapitola 21 Podrobnosti o konstruktorech tříd a instancí

21.7 Statický konstruktor, konstruktor třídy

Důležitá pravidla

21.8 Konstruktor instancí

„Roztroušená“ část

Tělo osloveného konstruktoru

Kapitola 22 Úvod do dědění implementace: Square, Mother – Daughter – Granddaughter

22.4 Konstruktor

22.5 Přetížené verze konstruktorů – použití super × this

22.8 Demonstrace chování konstruktorů

Kapitola 23 Zakrývání atributů a metod

23.2 Dědění metod

23.6 Zakrývání atributů předka

23.7 Metody nově definované v potomku

Kapitola 24 Virtuální metody a jejich přebíjení

24.1 Virtuální metody a jejich přebíjení

24.5 Zdokonalení třídy Square

24.7 Návrhový vzor Šablonová metoda (Template method)

Kapitola 25 Pasti a propasti dědění implementace

25.1 Třída XCRectangle

25.4 Řešení sloučením dědění a dekorátoru

25.6 Virtuální metody v konstruktoru

Kapitola 26 Vytváříme rodičovskou třídu – ARobot1

26.1 Abstraktní metody a třídy

Abstraktní a konkrétní metody

26.3 Návrhový vzor Stav s rodičovskou třídou

26.4 Rodičovská třída segmentů okruhu

Specifikace předků

Kapitola 27 Učíme program přemýšlet

27.4 Blok příkazů (složený příkaz)

27.5 Metoda equals(Object)

27.8 Zanořování podmíněných příkazů

27.10 Kaskáda možností

27.11 Přepínač – příkaz switch

27.12 Přepínač nad výčtovým typem

Kapitola 28 Ještě jednu rundu, prosím

Kapitola 29 Další důležité datové struktury

29.2 Kontejnery

29.5 Návrhový vzor Iterátor (Iterator)

Kapitola 30 O čem jsme ještě nehovořili

30.6 Slovo na závěr

netbeans.org/kb