Ján Hanák
Visual Basic praktické příklady
2010
Visual Basic 2010
MicrosoŌ
– praktické příklady
Ján Hanák
Nakladatelství a vydavatelství
Nakladatelství a vydavatelství
R
w w w. co m p u t e r m e d i a . c z w ww.c o m p u te r m e d i a. cz
R
®
TM
Visual Basic 2010 Express ®
Visual Basic 2010 - praktické příklady Visual Basic 2010 - praktické příklady Autor: Ing. Ján Hanák, Ph.D., MVP Recenzenti: prof. Ing. Peter Závodný, CSc., Ing. Magdaléna Cárachová, Ph.D. Návrh vnitřního layoutu: Pavel Navrátil, Ing. Michal Jiříček Zlom a sazba: Petr Fajks Návrh obálky: Ing. Michal Jiříček Jazyková úprava: Mgr. Ludmila Klatovská © Computer Media s.r.o. Vydání první, 2012 Všechna práva vyhrazena
ISBN: 978-80-7402-139-8
Žádná část této publikace nesmí být publikována a šířena žádným způsobem a v žádné podobě bez písemného svolení vydavatele. Názvy produktů a firem uvedených v knize mohou být registrovanými ochrannými známkami jejich vlastníků.
Computer Media s.r.o. Hrubčická 495 798 12 Kralice na Hané Česká republika Telefon: Fax: E-mail: Web:
+420 582 302 666 +420 582 302 667
[email protected] http://www.computermedia.cz
Kompletní nabídku literatury Computer Media s.r.o. můžete získat i objednat na internetové adrese www.computermedia.cz. Nakladatelství a vydavatelství
www.co m p ut ermedia.cz
2
R
VirtBook Book.cz .cz
Nový způsob výuky počítačových programů
Obsah Obsah O autorovi ..............................................................................................................................................................................5 Předmluva ............................................................................................................................................................................8 1. Objektové programování ...........................................................................................................................................10 Objektové programování
1.1. Deklarace třídy, členy třídy a instanciace třídy .....................................................................................................10 1.2. Přetížení konstruktoru ...........................................................................................................................................20 1.3. Sdílený konstruktor ...............................................................................................................................................24 1.4. Konstruktor a finalizér ...........................................................................................................................................27 1.5. Skalární vlastnost třídy ..........................................................................................................................................31 1.6. Automaticky implementované skalární vlastnosti třídy ........................................................................................35 1.7. Přetížení metody třídy.............................................................................................................................................39 1.8. Agregace a kompozice tříd .......................................................................................................................................44 1.9. Dědičnost tříd ..........................................................................................................................................................50 1.10. Polymorfismus implementovaný jednoduchou dědičností .....................................................................................57 1.11. Rozhraní ..................................................................................................................................................................61 1.12. Delegáti ...................................................................................................................................................................69 1.13. -výrazy .................................................................................................................................................................76 1.14. Anonymní třídy .......................................................................................................................................................83 1.15. XML konstanty ......................................................................................................................................................86 1.16. Rozšiřující metody ...................................................................................................................................................97 2. Technologické programování .................................................................................................................................100 2.1. Vizuální a událostní programování ......................................................................................................................100 2.2. Paralelní programování ........................................................................................................................................124
Technologické programování
2.3. LINQ......................................................................................................................................................................138
3
Visual Basic 2010 - praktické příklady
4
Úvod O autorovi
Objektové programování
Ing. Ján Hanák, Ph.D., MVP, vystudoval Ekonomickou univerzitu v Bratislavě. Zde, na Katedře aplikované informatiky Fakulty hospodářské informatiky (KAI FHI), pracuje jako vysokoškolský pedagog. Přednáší a vede semináře týkající se programování a vývoje počítačového softwaru v programovacích jazycích C, C++ a C#. Kromě zmíněné trojice jazyků patří k jeho oblíbeným programovacím prostředkům také Visual Basic, C++/CLI a F#. Je nadšeným autorem odborné počítačové literatury. V jeho portfoliu můžete najít následující knižní tituly: 1. Programování v jazyce Visual Basic 2010. Kralice na Hané: Computer Media, 2012. 2. Softvérové technológie na platforme Microsoft .NET. Bratislava: Eurokódex, 2011. 3. Programování v jazyce C. Kralice na Hané: Computer Media, 2011. 4. Rýchly vývoj aplikácií v jazyku Visual Basic 2010 pre systém Windows 7. Bratislava: Microsoft Slovakia, 2011. 5. Ako sa stať softvérovým vývojárom. Bratislava: Microsoft Slovakia, 2010. 6. C++: Akademický výučbový kurz. Bratislava: Vydavateľstvo EKONÓM, 2010. 7. C#: Akademický výučbový kurz, 2. aktualizované a rozšírené vydanie. Bratislava: Vydavateľstvo EKONÓM, 2010. 8. Inovácie v jazykoch Visual Basic 2010, C# 4.0 a C++. Brno: Artax, 2010. 9. Praktické objektové programování v jazyce C# 4.0. Brno: Artax, 2009. 10. Praktické paralelné programovanie v jazykoch C# 4.0 a C++. Brno: Artax, 2009.
Technologické programování
11. C++/CLI – Praktické príklady. Brno: Artax, 2009. 12. C++/CLI - Začínáme programovat. Brno: Artax, 2009. 13. C#: Akademický výučbový kurz. Bratislava: Vydavateľstvo EKONÓM, 2009. 14. Základy paralelného programovania v jazyku C# 3.0. Brno: Artax, 2009. 15. Objektovo orientované programovanie v jazyku C# 3.0. Brno: Artax, 2008. 16. Inovácie v jazyku Visual Basic 2008. Praha: Microsoft, 2008. 17. Visual Basic 2008: Grafické transformácie a ich optimalizácie. Bratislava: Microsoft Slovakia, 2008. 18. Programovanie B – Zbierka prednášok (Učebná pomôcka na programovanie v jazyku C++). Bratislava: Vydavateľstvo EKONÓM, 2008. 19. Programovanie A – Zbierka prednášok (Učebná pomôcka na programovanie v jazyku C). Bratislava: Vydavateľstvo EKONÓM, 2008.
5
Visual Basic 2010 - praktické příklady 20. Expanzívne šablóny: Príručka na tvorbu "code snippets" pre Visual Studio. Bratislava: Microsoft Slovakia, 2008. 21. Kryptografia: Príručka na praktické odskúšanie symetrického šifrovania v .NET Framework-u. Bratislava: Microsoft Slovakia, 2007. 22. Príručka na praktické odskúšanie vývoja nad Windows Mobile 6.0. Bratislava: Microsoft Slovakia, 2007. 23. Príručka na praktické odskúšanie vývoja nad DirectX. Bratislava: Microsoft Slovakia, 2007. 24. Príručka na praktické odskúšanie automatizácie aplikácií Microsoft Office 2007. Bratislava: Microsoft Slovakia, 2007. 25. Visual Basic 2005 pro pokročilé. Brno: Zoner Press, 2006. 26. C# - praktické příklady. Praha: Grada Publishing, 2006. 27. Programujeme v jazycích C++ s Managed Extensions a C++/CLI. Praha: Microsoft, 2006. 28. Přecházíme z jazyka Visual Basic 6.0 na jazyk Visual Basic 2005. Praha: Microsoft, 2005. 29. Visual Basic .NET 2003 – Začínáme programovat. Praha: Grada Publishing, 2004. Celosvětové vývojářské tituly Microsoft MVP V letech 2006 – 2012 byl jeho přínos vývojářským komunitám oceněn sedmi celosvětovými exkluzivními vývojářskými tituly Microsoft Most Valuable Professional (MVP) s kompetencí Visual Developer – Visual C++. Ján Hanák je jediným nositelem této kompetence zmíněného prestižního vývojářského titulu společnosti Microsoft v České republice a na Slovensku. Ocenění autora na poli didaktiky informatiky • Společnost Microsoft Slovakia udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2011 ocenění za nasazení nejnovějších vývojářských technologií do výukového procesu v publikaci „Inovácie v jazykoch Visual Basic 2010, C# 4.0 a C++“. • Společnost Microsoft Slovakia udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2010 ocenění za nasazení nejnovějších vývojářských technologií do výukového procesu v publikaci „Praktické paralelné programovanie v jazykoch C# 4.0 a C++“. • Společnost Microsoft Česká republika udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2009 ocenění za napsání první vysokoškolské učebnice „C++/CLI – Začínáme programovat“ o algoritmizaci a programování v jazyce C++/CLI.
6
Úvod • Společnost Microsoft Slovakia udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2009 ocenění za nasazení nejnovějších vývojářských technologií do výukového procesu v publikaci „Základy paralelného programovania v jazyku C# 3.0“.
Objektové programování
• Společnost Microsoft Česká republika udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2009 ocenění za mimořádně úspěšné odborné knižní publikace „Objektovo orientované programovanie v jazyku C# 3.0“ a „Inovácie v jazyku Visual Basic 2008“. • Společnost Microsoft Slovakia udělila Ing. Jánovi Hanákovi, Ph.D., MVP, v roce 2009 ocenění za zlepšování akademického ekosystému a za signifikantní rozšiřování technologií a programovacích jazyků Microsoftu na akademické půdě. • Společnost Grada Publishing udělila knize „C# - praktické příklady“ Ing. Jána Hanáka, Ph.D., MVP, v roce 2006 ocenění „Nejúspěšnější novinka vydavatelství Grada v oblasti programování za rok 2006“. Kontakt s vývojáři a programátory udržuje zejména prostřednictvím technických seminářů a odborných konferencí, na nichž aktivně vystupuje. Za všechny vybíráme tyto: • Vědecko-technický seminář Paralelné programovanie. KAI FHI EU a Microsoft Slovakia. Bratislava 21. 10. 2009. • Vědecko-technický seminář Novinky ve Visual C++ 2005. Microsoft Slovakia. Bratislava 3. 10. 2006. • Vědecko-technický seminář Visual Basic 2005 a jeho cesta k Windows Vista. Microsoft Slovakia. Bratislava 27. 4. 2006.
Technologické programování
Jako autor má letité zkušenosti s působením v elektronických a tištěných médiích. Během své kariéry pracoval na pozici odborného autora nebo odborného redaktora v následujících počítačových časopisech: PC WORLD, SOFTWARE DEVELOPER, CONNECT!, COMPUTERWORLD, INFOWARE, PC REVUE a CHIP. Dohromady publikoval více než 250 odborných a populárních prací věnovaných vývoji počítačového softwaru.
7
Visual Basic 2010 - praktické příklady Předmluva Visual Basic je jedním z nejpopulárnějších hybridních programovacích jazyků současné doby. Vývojáři, kteří používají jazyk Visual Basic při své práci, mohou vytvářet široké portfolio různorodých počítačových programů, od programů s vizuálním rozhraním až po webové aplikace. Kniha, kterou právě držíte v rukou, je věnována praktickému programování v jazyce Visual Basic ve verzi 2010. Jako taková tvoří publikace „Visual Basic 2010 – praktické příklady“ komplementární produkt ke knize „Programování v jazyce Visual Basic 2010“, kterou vydalo vydavatelství Computer Media v roce 2012. Zatímco zmíněná kniha podává základní programátorský kurz jazyka Visual Basic 2010, tato kniha se podrobněji věnuje ryze praktickému pohledu na různá programátorská paradigmata, jako je objektové programování, vizuální programování, událostní programování či paralelní programování. Kniha „Visual Basic 2010 – praktické příklady“ je členěna na dvě základní tematické části: 1. Objektové programování – tato část rozebírá paradigma objektově orientovaného programování (OOP) v jazyce Visual Basic 2010. 2. Technologické programování – tato část vykládá následující paradigmata programování v jazyce Visual Basic 2010: vizuální programování, událostní programování a paralelní programování. Intencí této knihy je dovést mírně pokročilé programátory v jazyce Visual Basic 2010 na úroveň pokročilých programátorů v tomto jazyce. Jsme hluboce přesvědčeni o tom, že žádný praktický vývojář v jazyce Visual Basic 2010 se neobejde bez solidních a vskutku hlubokých znalostí objektového programování v tomto prostředí. V zájmu vysvětlení všech jemných nuancí objektového programování je tomuto paradigmatu dedikována první část této publikace. V ní se čtenáři setkají se všemi principy OOP, k nimž patří objektová abstrakce, zapouzdření, dědičnost a polymorfismus. Po absolvování první části knihy pak mohou čtenáři přejít k její druhé části, v níž je předmětem výkladu praktické vizuální, událostní a paralelní programování. Kromě již popsaných paradigmat poskytuje kniha také demonstraci vybraných rysů funkcionálního programování, a to zejména v podkapitolách, jež charakterizují -výrazy a unifikovaný dotazovací jazyk LINQ. Při tvorbě programů, které jsou vyvíjeny v této knize, bylo použito integrované vývojové prostředí produktu Microsoft Visual Basic 2010 Express. Podotkněme, že tento produkt je zdarma dostupný pro všechny fanoušky jazyka Visual Basic. Samozřejmě, programovat v jazyce Visual Basic 2010 mohou vývojáři také v prostředí „velkého“ produktu Microsoft Visual Studio 2010, které také obsahuje spřízněné prostředí pro jazyk Visual Basic 2010.
8
Úvod
Objektové programování
Autor děkuje recenzentům této knihy, prof. Ing. Petru Závodnému, CSc., a Ing. Magdaléně Cárachové, PhD., za důkladné posouzení díla a podnětné náměty na jeho další vylepšení. Své srdeční poděkování autor adresuje také pánům z managementu vydavatelství Computer Media, jmenovitě Pavlu Navrátilovi a Ing. Michalu Jiříčkovi, a to za výtečnou spolupráci, ochotu a pečlivost, která byla věnována této knize od prvotního námětu až po finální výtisk. Ján Hanák
Technologické programování
Bratislava, květen 2012
9
Visual Basic 2010 - praktické příklady 1.
Objektové programování
1.1.
Deklarace třídy, členy třídy a instanciace třídy
Třída je v programovacím jazyce Visual Basic 2010 abstraktním objektovým uživatelsky deklarovaných odkazovým datovým typem. Jak víme, jazyk Visual Basic 2010 patří k hybridním programovacím jazykům s podporou objektového paradigmatu vývoje počítačového softwaru. Ve všech hybridních objektových programovacích jazycích je třída abstrakcí skutečných objektů, které z ní budou později vznikat. Z pohledu překladače jazyka Visual Basic 2010 je třída šablonou neboli továrnou na objekty, které budou obsahovat jistá data a které se budou jistým způsobem chovat. V jazyce Visual Basic 2010 deklarujeme třídu pomocí deklaračního příkazu Class: 'Deklarace nové třídy. Public Class Tiskarna 'Defi nice datových členů třídy. Private model As String Private vyrobce As String Private rychlostTisku As Integer 'Defi nice konstruktoru třídy. Public Sub New() New 'Explicitní inicializace datových členů třídy. model = "HP Photosmart D7200" vyrobce = "HP" rychlostTisku = 17 End Sub 'Defi nice metody třídy, která provádí tisk dokumentu. Public Sub Tisknout(ByVal ByVal dokument As String) String Console.WriteLine(dokument) End Sub 'Defi nice metody třídy, která tiskne diagnostickou stránku. Public Sub TisknoutDiagnostickouStranku() Console.WriteLine(vbCrLf &
10
1. Objektové programování "***** Toto je začátek diagnostické stránky tiskárny. *****") Console.WriteLine("Model tiskárny: {0}", model) Console.WriteLine("Výrobce tiskárny: {0}", vyrobce) Console.WriteLine("Rychlost tisku (stránky / minutu): {0}", Objektové programování
rychlostTisku) Console.WriteLine("***** Toto je konec diagnostické stránky " & "tiskárny. *****" & vbCrLf) End Sub End Class Deklarace třídy je důležitá, a to z následujících důvodů: 1. Uvádí abstrakci nového objektového datového typu v dané oblasti platnosti programu. V našem případě zavádíme nový abstraktní objektový typ s názvem Tiskarna, jenž bude v našem programu reprezentovat počítačovou tiskárnu. Tato skutečnost je významná zejména pro překladač, poněvadž ten není schopen vytvořit objekt třídy, aniž by znal její přesnou specifikaci. Poznámka: Podotkněme, že naprostá většina tříd je veřejných (tyto třídy jsou deklarovány s přístupovým modifikátorem Public), přičemž deklarační příkazy těchto tříd jsou uloženy v programovém modulu jazyka Visual Basic 2010.
Technologické programování
2. Každá správně deklarovaná třída představuje abstrakci nějaké množiny objektů ze skutečného světa. Naše třída Tiskarna kupříkladu nabízí abstrakci jakékoliv počítačové tiskárny, která se vyznačuje následujícími atributy: modelem, výrobcem a rychlostí tisku (poslední ze zmíněných atributů je měřen počtem vytištěných stránek textu za minutu, a to při standardní kvalitě tisku). Vyjma své datové stránky má každý objekt i funkční stránku, kterou charakterizujeme jako styl schování objektu. Přitom platí pravidlo, že objekty pocházející ze stejné třídy vykazují shodné chování. Tato behaviorální složka objektu je dána algoritmy, které jsou implementovány v metodách třídy. Při programování chování virtuálního objektu se snažíme o zachycení a přenos chování reálného objektu. Kupříkladu, každá počítačová tiskárna dovede vytisknout libovolný dokument. Rovněž tak, každá počítačová tiskárna umí vytisknout diagnostickou stránku se základními produktovými informacemi. Co jiného ještě počítačová tiskárna dělá? Vskutku hodně věcí: poradí si s vytištěním fotky z paměťové karty nebo USB klíče, vhodnou animací na zabudovaném LCD displeji nám poradí, jak vyměnit tiskové kazety či se bezdrátově spojí s foto-rámečkem a pošle do něj právě vytištěnou fotografii. Tohle všechno jsou ukázky činností neboli metod, které je počítačová tiskárna s to provést.
11
Visual Basic 2010 - praktické příklady 3. Všechny programové entity, jež se vyskytují v těle třídy, nazýváme členy třídy. Základními členy třídy jsou datové členy (známé také jako atributy) a funkční členy (známé také jako metody). Zatímco datové členy uchovávají data budoucích objektů třídy, metody slouží k provádění různorodých (a předem naprogramovaných) akcí, které budou budoucí objekty třídy schopny uskutečňovat. Pro vývojáře v jazyce Visual Basic 2010 je důležité toto sdělení: • Datové členy jsou technicky reprezentovány soukromými proměnnými, které jsou definovány na úrovni třídy. Je přímo nezbytné, aby byly všechny datové členy definované jako soukromé, tedy s přístupovým modifikátorem Private. Vysvětlení spočívá v respektování principu ukrývání dat, který je pro objektové programování příznačný. Tento princip zjednodušeně vyložíme takto: Nikdo, kromě objektu samotného, nemůže explicitně přistupovat k datům, jenž tento objekt uchovává ve svých datových členech. • Metody jsou technicky reprezentovány veřejně přístupnými procedurami Sub nebo funkcemi. Na rozdíl od datových členů chceme, aby byly definované metody veřejné (Public), protože bychom rádi umožnili klientům využívat služeb objektů, jež vzejdou z naší třídy. Pokud budeme abstrahovat od rigorózní a vpravdě pečlivé vědecké formulace, smíme konstatovat, že veřejné metody tvoří veřejně přístupné rozhraní objektu. Tato „zeď z metod“ je klientům objektu kdykoliv k dispozici a komunikace mezi klientem a objektem se rozproudí kdykoliv, když klient vyšle objektu signál (neboli zprávu, jak říkají objektoví vývojáři) o poskytnutí žádané služby. 4. Jak již bylo vzpomenuto, vedle atributů jsou skutečné objekty schopny provádět také řadu činností. V případě naší tiskárny půjde o tisknutí dokumentu (tuto činnost zabezpečuje metoda Tisknout) a vytištění diagnostické stránky (tuto činnost realizuje metoda TisknoutDiagnostickouStranku). Důležité: Už při navrhování třídy jakožto nového abstraktního objektového typu je velmi citelný princip zapouzdření (čili enkapsulace). Ten říká, že všechny atributy (datové členy) a všechny metody jsou uloženy v jednom kontejneru, jímž je třída samotná. Později, ve chvíli, kdy dojde k vytvoření objektu z deklarované třídy, bude i tento objekt respektovat princip zapouzdření. Speciální metodou třídy je konstruktor. Konstruktor je výjimečný v tom, že jde o výsostně inicalizační metodu, která je automaticky volána neprodleně po alokování objektu třídy. Úlohou konstruktoru je zabezpečit základní (často říkáme implicitní) inicializaci všech datových členů, které objekt třídy obsahuje. Smyslem uskutečnění základní inicializace je získat objekt ve výchozím a okamžitě použitelném stavu. V jazyce Visual Basic 2010 je syntaktickou reprezentací konstruktoru veřejně přístupná procedura Sub s identifikátorem New a prázdnou nebo plnou signaturou.
12
1. Objektové programování
Objektové programování
Poznámka: Termínem signatura označujeme v textu této knihy syntaktickou část za jménem konstruktoru (New), která se nachází v závorkách. V objektovém programování může být konstruktor buď bezparametrický (je-li jeho signatura prázdná), nebo parametrický (nacházejí-li se v jeho signatuře formální parametry). Jak uvedeme v jedné z nastávajících podkapitol, jazyk Visual Basic 2010 nám umožňuje konstruktor přetížit. Jako vývojáři tak umíme zavést do těla třídy více definicí konstruktoru, které se liší právě svými signaturami. Jakmile je třída deklarována v programovém modulu, můžeme ji instanciovat. Termínem „instanciace třídy“ označujeme proces generování objektu z příslušné třídy. Instanci čili objekt třídy vytvoříme v jazyce Visual Basic 2010 takto: Sub Main() 'Vytvoření nového objektu z třídy. Dim domaciTiskarna As Tiskarna = New Tiskarna() End Sub V příkazu pro vytvoření nového objektu třídy Tiskarna figurují tyto entity: • Klíčové slovo Dim, které definuje novou odkazovou proměnnou. • Odkazová proměnná s názvem domaciTiskarna, do níž bude později uložen odkaz na vygenerovaný objekt třídy Tiskarna. • Klíčové slovo As determinuje datový typ odkazové proměnné domaciTiskarna. • Přiřazovací operátor (=).
Technologické programování
• Operátor New. • Název třídy, kterou hodláme instanciovat (Tiskarna v našem případě). • () – prázdné závorky jsou v tomto kontextu nepovinnou součástí, přičemž explicitně poukazují na fakt, že alokovaný objekt bude inicializován bezparametrickým konstruktorem. Komentář k fragmentu zdrojového kódu jazyka Visual Basic 2010: Představený instanciační příkaz je ve skutečnosti přiřazovacím příkazem. Podobně jako každý přiřazovací příkaz, i tento obsahuje levou a pravou stranu. Na levé straně se nachází definiční výraz Dim domaciTiskarna As Tiskarna, který vytváří novou odkazovou proměnnou se stanoveným identifikátorem a datovým typem. Poznámka: Adjektivum „odkazová“ uvádíme při proměnné domaciTiskarna proto, že jejím typem je třída Tiskarna. Nuže a tato třída, ostatně stejně jako všechny třídy jazyka Visual Basic 2010, se řadí k odkazovým (a nikoliv hodnotovým) datovým typům.
13
Visual Basic 2010 - praktické příklady Tip: Do pozornosti dáváme užitečnou pomůcku, s jejíž pomocí si lépe zapamatujeme lexikální význam odkazových proměnných: Všechny odkazové proměnné uchovávají odkazy na instance (objekty) odkazových typů (jako jsou kupříkladu třídy), které sídlí v řízené haldě. S instancemi (objekty) odkazových typů nelze manipulovat přímo, ale jenom přes odkazy, jež jsou uloženy v příslušných odkazových proměnných. Odkazová proměnná domaciTiskarna je uložena v zásobníku, tedy v automatické paměťové oblasti aplikační domény fyzického procesu řízeného programu jazyka Visual Basic 2010. Pro úplnost dodejme, že se jedná o lokální automatickou odkazovou proměnnou, což vyplývá z pozice definičního výrazu (ten se vyskytuje v těle hlavní metody Main programu). Automatické lokální proměnné jsou samočinně zlikvidovány poté, co vyprší oblast jejich platnosti (to se stane tehdy, když se dokončí zpracování hlavní metody Main). Výraz napravo od operátoru = je instanciačním výrazem. Jeho syntaktický obraz je New Tiskarna(). Operátor New je instanciačním operátorem, čili instanci třídy vytvářejícím operátorem. Poznámka: V jazyce Visual Basic 2010 dokážeme vytvářet objekty pojmenovaných a anonymních tříd. V této podkapitole rozebíráme instanciaci pojmenovaných tříd. Ve všeobecnosti můžeme prohlásit, že pokaždé, když ve zdrojovém kódu programu spatříme výraz New Trida(), tak půjde o generování objektu pojmenované třídy. Intuitivně cítíme, že pojmenovaná třída je každá třída, která disponuje svým identifikátorem. Opakem pojmenované třídy je anonymní třída, zjednodušeně třída beze jména. O anonymních třídách, jejich deklaraci a instanciaci pojednáme v jedné z nadcházejících podkapitol této publikace. Z technického hlediska se při instanciaci třídy odehrávají tyto akce: 1. Překladač emituje instrukce, které správci paměti nařídí, aby v řízené haldě vyhledal dostatečně velký paměťový blok, do něhož bude možné nový objekt naší třídy uložit. 2. Je-li paměťový blok o požadované velikosti nalezen, nastartuje se alokace objektu. To v tomto kontextu znamená, že do předem přichystaného paměťového bloku se uskladní data a metody objektu. 3. Po úspěšné alokaci objektu dochází k jeho inicializaci. V této chvíli je prostředím CLR automaticky volán konstruktor objektu, který objekt uvede do okamžitě použitelného stavu. Jako „okamžitě použitelný stav“ definujeme stav, kdy je vytvořený objekt schopen plnit požadavky svých klientů. 4. Poté, co je objekt řádně inicializován, předá prostředí CLR odkaz na něj, který přijímá náš programový kód. Získaný odkaz na vygenerovaný objekt je cenným zdrojem a my jej ukládáme do odkazové proměnné.
14
1. Objektové programování
Objektové programování
Zkoumaný instanciační výraz New Tiskarna() můžeme v daném kontextu charakterizovat také jako inicializační výraz (je totiž umístěn na pravé straně přiřazovacího příkazu). Jelikož asociativita přiřazovacího operátoru je ve směru zprava doleva (), je zřejmé, že nejprve je nutno vyhodnotit instanciační výraz a až poté smíme pokračovat dál. Hodnotou analyzovaného výrazu je odkaz na úspěšně alokovaný a inicializovaný objekt třídy Tiskarna. Kdybychom chtěli získanou hodnotu reprezentovat symbolicky, tak bychom napsali, že Tiskarna je hodnotou instanciačního výrazu New Tiskarna(). Důležité: Po zpracování instanciačního příkazu existuje v operační paměti právě jeden objekt třídy Tiskarna, právě jedna odkazová proměnná s typem Tiskarna a právě jeden odkaz na objekt třídy Tiskarna, který je uskladněn v odkazové proměnné typu Tiskarna. Mezi odkazovou proměnnou s odkazem na objekt třídy Tiskarna a samotným objektem třídy Tiskarna panuje relace typu 1:1. Relace mezi odkazem na objekt a objektem samotným je velice silná: Pokud totiž dojde k likvidaci odkazu na objekt třídy Tiskarna, zanedlouho bude destrukci podroben také samotný objekt třídy Tiskarna. Služeb zhotoveného objektu využíváme voláním metod objektu, a to takhle: Sub Main() Dim domaciTiskarna As Tiskarna = New Tiskarna() domaciTiskarna.Tisknout("Toto je ukázkový dokument.") domaciTiskarna.TisknoutDiagnostickouStranku() End Sub
Technologické programování
Při volání metody objektu upotřebíme tečkový operátor (nebo-li operátor přímého přístupu) a určíme název metody, s níž si přejeme pracovat. Jestliže je volaná metoda parametrická (což je třeba případ metody Tisknout), tak za názvem metody zadáváme závorky, v nichž jsou specifikována vstupní data (samozřejmě, v požadovaném formátu a datovém typu). Není-li volaná metoda parametrická, zapisujeme za jejím názvem pouze prázdné závorky (jako u metody TisknoutDiagnostickouStranku). Virtuální počítačová tiskárna existuje tak dlouho, dokud se nezničí odkaz na ni. To přesněji znamená, že objekt třídy Tiskarna umírá záhy poté, co byla ze zásobníku odstraněna adekvátní odkazová proměnná. Za předpokladu, že nikde jinde v programu neexistuje žádná další inicializovaná odkazová proměnná identického datového typu, správce paměti usoudí, že virtuální tiskárna není nadále využívána, a proto ji bez zbytečných okolků zlikviduje.
15
Visual Basic 2010 - praktické příklady Důležité: Správce paměti (angl. Garbage Collector, GC) je softwarový stroj, který automaticky řídí životy objektů odkazových datových typů. Správce paměti je součástí prostředí CLR, z čehož je zřejmé, že jde o stroj, který je implicitně k dispozici všem řízeným programům, jež napíšeme v jazyce Visual Basic 2010. Správce paměti sleduje míru využití objektů uložených v řízené haldě, a pokud zjistí, že jisté objekty jsou nepotřebné, automaticky je uvolní. Model chování správce paměti je naprogramován tak, aby byly paměťové zdroje využívány s nejvyšší možnou mírou efektivity. Práci s objekty v jazyce Visual Basic 2010 lze popsat pomocí následujícího 3krokového pracovního modelu: 1. Deklarace třídy jako nového abstraktního objektového datového typu. 2. Instanciace třídy a vytvoření instance (objektu) třídy. 3. Využívání služeb instance (objektu) třídy. Předestřený model počítá s tím, že jako VB-vývojáři budeme chtít vždy deklarovat své vlastní třídy. To ovšem není pokaždé nutné, neboť v bázové knihovně třídy (BCL) jsou umístěny stovky předem deklarovaných tříd. Tyto třídy mohou programátoři okamžitě instanciovat, čímž se nám z původního 3krokového modelu stává model pouze 2krokový. Na závěr této podkapitoly jsme ponechali syntaktické triky, které můžeme upotřebit při vytváření nových objektů našich tříd: 1. Původní instanciační příkaz smíme syntakticky zjednodušit do následující podoby: Dim domaciTiskarna As New Tiskarna() Udělali jsme tyto syntaktické změny: • Vypustili jsme explicitní specifikaci datového typu odkazové proměnné. • Odstranili jsme přiřazovací operátor. Nyní již příkaz není přiřazovacím, avšak stále zůstává příkazem instanciačním. Jazyk Visual Basic 2010 je silně typový a překladač dovede odkazové proměnné domaciTiskarna přiřadit odpovídající datový typ (třídu Tiskarna). 2. Původní instanční příkaz je agregovaný, a proto jej můžeme rozdělit na dva samostatné příkazy: Dim domaciTiskarna As Tiskarna ... domaciTiskarna = New Tiskarna() První z příkazů je ryze definiční, neboť jeho smyslem je zavést novou odkazovou proměnnou typu Tiskarna. Druhý příkaz, který může být od prvního libovolně vzdálený,
16
1. Objektové programování
Objektové programování
je inicializačním příkazem (to poznáme snadno podle toho, že ve skutečnosti dochází k inicializaci odkazové proměnné, jež byla definována dříve). Tato ukázka předvádí takzvanou odloženou inicializaci odkazové proměnné a konec konců také odloženou instanciaci třídy Tiskarna. Odložená instanciace je vhodná technika, která se využívá tehdy, když objekt třídy nepotřebujeme okamžitě při vytvoření odkazové proměnné, ale přesto víme, že jej budeme někdy v budoucnu potřebovat. Vygenerovat objekt třídy můžeme v jazyce Visual Basic 2010 i takto: Dim domaciTiskarna = New Tiskarna() Všimněme si, že v definičním výrazu odkazové proměnné domaciTiskarna jsme úplně vynechali specifikaci datového typu. Ačkoliv v raných verzích jazyka Visual Basic mohli vývojáři pracovat s netypovými proměnnými, počínaje první „dotnetovou“ edicí se Visual Basic stal striktně typovým jazykem. Jazyková specifikace byla rozšířena o volbu Option Strict, která když je aktivní (Option Strict On), přikazuje, že všechny řádně definované proměnné musejí mít svůj datový typ. Až do verze 2008 jazyka Visual Basic byl tento formalismus jasně dán. Pak došlo k zapracování mechanismu typové inference, jehož činnost je řízena nově dodanou volbou Option Infer. Je-li tato volba aktivní (Option Infer On), tak překladač jazyka Visual Basic 2010 inferuje (čili strojově odvozuje) datový typ proměnné podle typu hodnoty jejího inicializačního výrazu. Práci mechanismu typové inference demonstruje i výše zapsaný instanciační příkaz. Vysvětlení je nasnadě: překladač dokáže již v čase překladu přesně stanovit typ odkazové proměnné domaciTiskarna, poněvadž lze vyhodnotit její inicializační výraz. Jak je známo, inicializační výraz je ve skutečnosti instanciačním výrazem, jehož hodnotou je typově silný odkaz na typově silný objekt třídy Tiskarna.
Technologické programování
Přestože je uvedený instanciační příkaz syntakticky a sémanticky v pořádku, rádi bychom dodali, že v případě instanciace pojmenovaných tříd se vždy snažíme sami explicitně určit datový typ příslušných odkazových proměnných. Naopak, služeb mechanismu typové inference s díkem využíváme při vytváření objektů anonymních tříd. Členy, které se objevují v deklaraci třídy, mohou být: • instanční, • sdílené. K instančním členům patří instanční datové členy a instanční funkční členy, respektive instanční metody. K sdíleným členům se zase řadí sdílené datové členy a sdílené metody. Základní rozdíl mezi instančními a sdílenými členy je následující: Instanční členy jsou vždy spojeny s konkrétní instancí třídy (čili s konkrétním objektem), zatímco sdílené členy třídy jsou asociovány s třídou samotnou (a nikoliv s instancemi této třídy). Pro lepší a snadnější pochopení si pomozme praktickým příkladem. Dejme tomu, že vytvoříme 10 objektů naší třídy Tiskarna. Jelikož datové členy, které jsme uvedli v deklaraci této třídy,
17
Visual Basic 2010 - praktické příklady jsou ryze instanční, každý ze sestrojených deseti objektů třídy Tiskarna bude disponovat svou vlastní množinou datových členů, jež charakterizují model tiskárny, jejího výrobce a rychlost tisku. Samozřejmě, hodnoty jednotlivých datových členů se mohou napříč různými objekty lišit – třeba výrobcem 5 tiskáren může být firma Epson a výrobcem zbývajících pěti tiskáren zase společnost HP. Instanční metoda je metoda, která může být zavolána vždy pouze v souvislosti s instancí (objektem) dané třídy. Nemáme-li po ruce objekt třídy, nemůžeme ani zavolat jeho instanční metodu. Veškeré metody třídy Tiskarna jsou instanční. Když se podíváme na jejich syntaktické obrazy, zjistíme, že v jazyce Visual Basic 2010 jsou všechny metody implicitně instanční. To ve zkratce znamená, že při definici instanční metody nemusíme používat žádná speciální klíčová slova či modifikátory. Na druhou stranu, v hlavičce sdílené metody je vždy zřetelně uveden modifikátor Shared. Stejnojmenný modifikátor stojí také v definičních příkazech sdílených datových členů. Sdílená metoda smí být vyvolána, aniž by nejprve došlo k instanciaci třídy. Tato skutečnost je v programátorských kruzích považována za největší konkurenční výhodu sdílených metod. Dobrá, ovšem jaký to má vůbec smysl? Inu, někdy můžeme chtít zjistit informace o třídě samotné nebo o všech doposud vytvořených objektech této třídy. Jak již plyne z jejich názvů, sdílené datové členy mohou být sdíleny všemi objekty třídy. Kdybychom se chtěli kupříkladu dopátrat počtu vygenerovaných virtuálních tiskáren, mohli bychom využít sdílenou metodu, která by nám tuto informaci poskytla na požádání. Za těchto okolností by se syntaktický skelet třídy Tiskarna změnil takto: Public Class Tiskarna Private model As String Private vyrobce As String Private rychlostTisku As Integer 'Defi nice sdíleného datového členu třídy. Private Shared pocetTiskaren As Integer Public Sub New() New model = "HP Photosmart D7200" vyrobce = "HP" rychlostTisku = 17 pocetTiskaren += 1 End Sub Public Sub Tisknout(ByVal ByVal dokument As String) String
18
1. Objektové programování Console.WriteLine(dokument) End Sub Public Sub TisknoutDiagnostickouStranku() Console.WriteLine(vbCrLf & Objektové programování
"***** Toto je začátek diagnostické stránky tiskárny. *****") Console.WriteLine("Model tiskárny: {0}", model) Console.WriteLine("Výrobce tiskárny: {0}", vyrobce) Console.WriteLine("Rychlost tisku (stránky / minutu): {0}", rychlostTisku) Console.WriteLine("***** Toto je konec diagnostické " & "stránky tiskárny. *****" & vbCrLf) End Sub 'Defi nice sdílené metody třídy. Public Shared Function SpocitatTiskarny() As Integer Return pocetTiskaren End Function End Class
Technologické programování
Komentář k fragmentu zdrojového kódu jazyka Visual Basic 2010: Do těla třídy Tiskarna jsme umístili jeden sdílený datový člen pocetTiskaren typu Integer a jednu sdílenou metodu SpocitatTiskarny. Sdílená metoda je implementována jako funkce navracející aktuální hodnotu celočíselného sdíleného datového členu pocetTiskaren. Budeme-li chtít, aby nám sdílená metoda SpocitatTiskarny poskytla informaci o všech vytvořených virtuálních tiskárnách, budeme muset inkrementovat hodnotu sdíleného datového členu pocetTiskaren. K inkrementaci dojde pokaždé, když bude vytvořena nová tiskárna – to je přesně úkol pro konstruktor naší třídy. Použití sdílené metody dokumentuje následující fragment zdrojového kódu jazyka Visual Basic 2010: Sub Main() Dim tiskarny(9) As Tiskarna For t As Integer = 0 To tiskarny.GetUpperBound(0) tiskarny(t) = New Tiskarna() Next
19
Visual Basic 2010 - praktické příklady Dim pocetTiskaren As Integer = Tiskarna.SpocitatTiskarny() Console.WriteLine("Počet vytvořených tiskáren: {0}.", pocetTiskaren) End Sub Komentář k fragmentu zdrojového kódu jazyka Visual Basic 2010: Začínáme vytvořením jednorozměrného pole tiskarny, do něhož se vejde 10 tiskáren (objektů třídy Tiskarna). V dalším kroku startujeme cyklus For, v němž vygenerujeme 10 tiskáren a vložíme je do přichystaného pole. Nakonec voláme sdílenou metodu SpocitatTiskarny a zjišťujeme, kolikže tiskáren jsme vlastně vytvořili. Předestřený kód názorně ukazuje, že k volání sdílené metody nám stačí pouze třída, čemuž plně odpovídá aktivační výraz ve tvaru Tiskarna.SpocitatTiskarny(). Při práci s instančními a sdíleným členy třídy musíme mít na paměti bezpečné komunikační modely: 1. bezpečný komunikační model: Instanční metoda manipuluje s instančními datovými členy. 2. bezpečný komunikační model: Sdílená metoda manipuluje se sdílenými datovými členy. 3. bezpečný komunikační model: Instanční metoda manipuluje se sdílenými datovými členy. Opět máme pro vás pohotovou pomůcku: vše probíhá v pořádku, když se shodují druhy členů, které mají mezi sebou komunikovat. Není proto překvapením, že instanční metody mohou komunikovat s instančními datovými členy, zatímco sdílené metody smí vést informační dialog se sdílenými datovými členy. Analogicky, bezpečná je i komunikace instanční metody se sdílenými datovými členy (důvode je pochopitelný, vždyť sdílené datové členy jsou sdíleny všemi vygenerovanými objekty dané třídy). Pozor si musíme dát tehdy, když bychom chtěli přistupovat z těla sdílené metody k instančním datovým členům. Tato kompozice není bezpečná, a proto ani dovolená. A zde je vysvětlení, proč je tomu tak: Instanční datový člen je vždycky spojen s konkrétní instancí třídy. Ovšem na druhou stranu, sdílená metoda může být aktivována i tehdy, neexistuje-li žádná instance třídy. Nuže, a pokud nemáme žádnou instanci třídy, nemůžeme logicky mít ani žádný z jejích datových členů.
1.2. Přetížení konstruktoru Konstruktor je metoda inicializačního charakteru, která se vyskytuje v deklaraci každé třídy, a to buď implicitně, anebo explicitně. Syntakticky je konstruktor veřejnou metodou s identifikátorem New. Pokud vývojář nezavede do těla třídy definici konstruktoru, překladač vygeneruje svůj vlastní, takzvaný implicitní konstruktor, a ten poté vloží do těla třídy. Implicitní konstruktor je vždy veřejně přístupný a bezparametrický (čili s prázdnou signaturou). Implicitní konstruktor provádí implicitní inicializaci všech instančních datových členů třídy.
20
1. Objektové programování
Objektové programování
Poznámka: Na rozdíl od programovacího jazyka C++, jazyk Visual Basic 2010 automaticky zajišťuje implicitní inicializaci všech datových členů zrozených objektů. V procesu implicitní inicializace jsou integrální hodnotové datové členy nastaveny na nulu (v celočíselném nebo reálném vyjádření), znakové hodnotové datové členy jsou nastaveny na nulový znak a logické hodnotové datové členy jsou nastaveny na logickou nepravdu (False). Pokud je naše třída podtřídou, její implicitní konstruktor automaticky volá implicitní konstruktor bázové třídy. Často se nám stává, že se stylem práce implicitního konstruktoru nejsme spokojeni. Pak nám nezbývá, než dodat do těla třída náš vlastní, explicitní konstruktor. Tvorba konstruktoru je řízena všeobecně platnými pravidly: • Konstruktor je veřejně přístupnou metodou třídy, která je implementována jako procedura Sub. • Jméno konstruktoru je New. • Konstruktor smí být bezparametrický (s prázdnou signaturou) anebo parametrický (se signaturou naplněnou řádně definovanými formálními parametry). Nachází-li se v těle třídy explicitní konstruktor, překladač nikdy nevytváří svůj vlastní implicitní konstruktor (připomeňme, že generování implicitního konstruktoru se děje pouze tehdy, když překladač nenalezne v těle třídy explicitní konstruktor). Podstatou techniky přetížení konstruktoru je dodání více definic konstruktor do těla jedné třídy. Přitom musí být splněna nutná podmínka diferenciace všech přítomných verzí konstruktoru. Řečeno méně formálně, definice konstruktoru se musejí lišit svými signaturami. To pod drobnohledem znamená následující:
Technologické programování
• V těle třídy se smí nacházet právě jeden bezparametrický konstruktor. • V těle třídy se musí nacházet konečná a neprázdná množina parametrických konstruktorů, které se liší svými signaturami. • Odlišnosti mezi signaturami parametrických konstruktorů spočívají v různém počtu formálních parametrů, v různých datových typech formálních parametrů anebo v různém pořadí formálních parametrů. Jsou-li splněny uvedené požadavky, mluvíme o konstruktoru třídy jako o přetíženém. Přetížení konstruktoru je zpravidla výhodné, neboť skýtá programátorovi více možných inicializačních variant alokovaných objektů dané třídy. Jako první praktickou ukázku zvolíme třídu Automobil, kterou navrhneme tak, aby pracovala s přetíženým konstruktorem.
21
Visual Basic 2010 - praktické příklady Public Class Automobil Private model As String Private vykon As Short Private barva As Color 'Defi nice bezparametrické verze konstruktoru. Public Sub New() New model = "Suzuki Swift" vykon = 69 barva = Color.Red End Sub 'Defi nice parametrické verze konstruktoru. Public Sub New(ByVal model As String, ByVal vykon As Short, Short ByVal barva As Color) Me.model = model Me Me.vykon = vykon Me Me.barva = barva Me End Sub Public Sub KonfiguraceAuta() Console.WriteLine("Máte auto s následujícími parametry:") Console.WriteLine("Model: {0}" & vbCrLf & "Výkon: {1}" & vbCrLf & "Barva: {2}", model, vykon, barva) End Sub End Class Komentář k zdrojovému kódu jazyka Visual Basic 2010: Třída Automobil obsahuje tři soukromé datové členy, které popisují model, výkon (měřen v KW) a barvu auta. Dále se v těle třídy vyskytují dvě verze konstruktoru: první je bezparametrická a druhá je parametrická. Vzhledem k tomu, že syntakticky jsou obě varianty konstruktoru navrženy správně, můžeme konstatovat, že konstruktor třídy Automobil je přetížený. Podívejme se nyní, jak se obě definice konstruktoru staví k otázce inicializace vygenerovaného objektu třídy Automobil. Když použijeme první (bezparametrickou) verzi konstruktoru, získáme automobil Suzuki Swift s motorem o výkonu 69 KW a s karoserií červené barvy.
22
1. Objektové programování To je zcela jasné, neboť hodnoty odpovídající zmíněným charakteristikám vozu jsou v těle bezparametrického konstruktoru fixně uloženy do příslušných datových členů třídy.
Objektové programování
Podíváme-li se na druhou (parametrickou) verzi konstruktoru, spatříme daleko vyšší míru konfigurovatelnosti. Předcházející tvrzení rádi dokážeme. V signatuře parametrického konstruktoru se totiž objevují tři formální parametry (s identifikátory model, vykon a barva), které mohou být inicializovány libovolnými argumenty, jež určí vývojář při generování objektu nového automobilu. Parametrická verze konstruktoru proto provádí klientem řízenou inicializaci alokovaného objektu třídy Automobil. Poznámka: Po prostudování zdrojového kódu parametrického konstruktoru přijdeme na to, že názvy formálních parametrů jsou lexikálně zcela shodné s názvy datových členů třídy. To je v pořádku, a to i v jazyce Visual Basic 2010, který, jak víme, není citlivý na velikost textových znaků uváděných v identifikátorech programových entit. Nicméně v těle parametrického konstruktoru potřebujeme mít sadu přiřazovacích příkazů, jejichž pomocí vložíme do datových členů třídy kýžené inicializační hodnoty. Jak to ovšem udělat, když detekujeme shodu v názvech datových členů a formálních parametrů parametrického konstruktoru? Fintou je použití klíčového slova Me ve výrazu Me.model, který syntakticky přesně určuje datový člen třídy a nikoliv stejnojmenný formální parametr. Máme-li hotovou deklaraci třídy Automobil s přetíženým konstruktorem, můžeme jeho schopnosti využít při zakládání objektů této třídy: Sub Main() 'Vytvoření 1. objektu – objekt je inicializován bezparametrickým
Technologické programování
'konstruktorem. Dim mojePrvniAuto As New Automobil() mojePrvniAuto.KonfiguraceAuta() 'Vytvoření 2. objektu – objekt je inicializován parametrickým 'konstruktorem. Dim mojeDruheAuto As New Automobil("VW Polo", 77, Color.Blue) mojeDruheAuto.KonfiguraceAuta() End Sub Komentář k zdrojovému kódu jazyka Visual Basic 2010: První objekt, jejž zhotovíme, je inicializován bezparametrickým konstruktorem. V odkazové proměnné mojePrvniAuto bude proto uložen odkaz na objekt třídy Automobil, který reprezentuje vůz značky Suzuki. Docela jiná situace je u druhého vytvořeného automobilu. Jelikož se můžeme sami
23
Visual Basic 2010 - praktické příklady rozhodnout, jaký vůz chceme, využíváme služeb parametrického konstruktoru a ve finále získáváme automobil VW Polo s motorem o výkonu 77 KW a modrou barvou karoserie. Pro úplnost výkladu dodejme, že nechť už se ve třídě nachází variabilní počet verzí přetíženého konstruktoru, inicializaci objektu třídy bude vždy provádět právě jeden konstruktor. Proces selekce optimální verze přetíženého konstruktoru je uskutečňován překladačem, přičemž probíhá zhruba v těchto krocích: 1. Překladač zjistí celkový počet verzí přetíženého konstruktoru v deklaraci třídy. 2. Překladač vyloučí ty verze přetíženého konstruktoru, které nevyhovují dodanému počtu argumentů. Kupříkladu, když je klientským kódem volán konstruktor, jemuž jsou poskytnuty tři argumenty, překladač vyřadí bezparametrickou verzi přetíženého konstruktoru a rovněž tak i všechny parametrické verze přetíženého konstruktoru, které mají méně (2) nebo více (>3) formálních parametrů. 3. V tuto chvíli má překladač k dispozici kompletní soupravu parametrických verzí přetíženého konstruktoru, jež obsahují tři formální parametry. Překladač pokračuje testem úplné typové shody, při kterém analyzuje, zda mezi datovými typy jednotlivých argumentů a datovými typy odpovídajících formálních parametrů existuje úplná shoda. To se stane například tehdy, když jsou klientským kódem poskytnuty tři celočíselné argumenty typu Integer a v deklaraci třídy se vyskytuje parametrická verze přetíženého konstruktoru se třemi formálními parametry rovněž typu Integer. Je-li test úplné typové shody úspěšný, říkáme, že byla nalezena optimální varianta přetíženého konstruktoru. Ihned poté, co se tak stane, je optimální varianta přetíženého konstruktoru vyvolána a jsou zpracovány všechny inicializační příkazy v ní obsažené. 4. Naopak, není-li test úplné typové shody úspěšný, znamená to, že neexistuje žádná optimální varianta přetíženého konstruktoru. Je však stále možné, že v těle třídy je situována vyhovující verze přetíženého konstruktoru. Jako vyhovující označujeme takovou verzi, pro kterou je nutné provést nejméně implicitních typových konverzí. (Předmětem implicitního přetypování jsou typy argumentů, poněvadž s typy formálních parametrů překladač již nic dělat nemůže.) Když se podaří jednoznačně vybrat vyhovující variantu přetíženého konstruktoru, je vyvolána tato. V opačném případě je překladačem generováno chybové hlášení, které pojednává o neúspěchu ve výběru vhodné varianty přetíženého konstruktoru.
1.3.
Sdílený konstruktor
V jazyce Visual Basic 2010 můžeme kromě instančního konstruktoru pracovat také se sdíleným konstruktorem. V hlavičce sdíleného konstruktoru stojí klíčové slovo Shared, jinak je sdílený konstruktor rovněž jako jeho instanční ekvivalent procedurou Sub s identifikátorem New.
24
1. Objektové programování Na sdílený konstruktor jsou však kladeny další požadavky: • Sdílený konstruktor nesmí být přetížen. • Sdílený konstruktor se musí vyskytovat v právě jednom bezparametrickém vyhotovení.
Objektové programování
• Sdílený konstruktor nesmí explicitně specifikovat žádný přístupový modifikátor (sdílený konstruktor je implicitně soukromý). Je pochopitelné, že sdílený konstruktor slouží k inicializaci sdílených datových členů třídy. Sdílený konstruktor je automaticky aktivován ihned poté, co je třída (v níž se tento konstruktor nachází) načtena do operační paměti počítače. V těle sdíleného konstruktoru se mohou nacházet jakékoliv smysluplné a syntakticky správně navržené příkazy, jejichž cílem je inicializace sdílených datových členů třídy. Dovednosti sdíleného konstruktoru a potažmo i možnosti dalších sdílených členů si ukážeme na třídě, jež bude představovat shluk buněk. Public Class ShlukBunek 'Defi nice sdíleného datového členu třídy. Private Shared pocetBunek As Long 'Defi nice sdíleného konstruktoru. Shared Sub New() New 'Inicializace sdíleného datového členu. pocetBunek = 10 End Sub Technologické programování
'Defi nice sdílené metody. Public Shared Sub Regenerovat() pocetBunek *= 2 End Sub 'Defi nice sdílené metody. Public Shared Function ZjistitVelikostShluku() As Long Return pocetBunek End Function End Class Komentář k zdrojovému kódu jazyka Visual Basic 2010: Z biologického hlediska budeme za shluk buněk považovat konečnou množinu buněk, které formují část tkáně. S jistou dávkou abstrakce navrhneme jednoduchý matematický model regenerace buněk,
25
Visual Basic 2010 - praktické příklady který budeme syntakticky reprezentovat třídou ShlukBunek opatřenou sdílenými členy. Podívejme se, co nás v těle třídy čeká. Tak předně vidíme sdílený datový člen pocetBunek typu Long, který bude odrážet celkový počet buněk v tkáni. Pak přichází sdílený konstruktor, jejž jsme sestavili přesně podle požadavků překladače. Sdílený konstruktor inicializuje sdílený datový člen pocetBunek. Deklaraci třídy uzavírají dvě sdílené metody s názvy Regenerovat a ZjistitVelikostShluku. Sdílená metoda Regenerovat simuluje množení buněk, a to tak, že zdvojnásobí aktuální počet buněk. Sdílená metoda ZjistitVelikostShluku nám na požádání poskytne celkový počet buněk tkáně. Třídu ShlukBunek a její sdílené členy využijeme takhle: Sub Main() For i = 1 To 20 ShlukBunek.Regenerovat() Console.WriteLine("Aktuální počet buněk ve shluku: {0}.", ShlukBunek.ZjistitVelikostShluku()) Next End Sub Když bude třída ShlukBunek načtena do operační paměti počítače, alokuje se její sdílený datový člen pocetBunek. Prostředí CLR aktivuje sdílený konstruktor, jenž uskuteční explicitní inicializaci sdíleného datového členu pocetBunek. Vedle sdíleného datového členu jsou alokovány rovněž sdílené metody Regenerovat a ZjistitVelikostShluku. V hlavní metodě Main provádí cyklus For své iterace, přičemž v každé jedné z nich zavolá sdílenou „regenerační“ metodu. Postupným voláním této metody dochází k růstu velikosti shluku buněk. Trend růstu dokumentuje volání sdílené metody ZjistitVelikostShluku. Jelikož je tato sdílená metoda volána v každé iteraci cyklu For, může uživatel sledovat celkem strmý nárůst buněk tkáně (obr. 1.1).
Obr. 1.1: Výstup simulačního modelu regenerace buněk
26
1. Objektové programování 1.4.
Konstruktor a finalizér
Konstruktor je metoda, která uvádí objekty do okamžitě použitelných stavů. Konstruktor je volán vždy, když je objekt alokován. Ve skutečnosti je vazba mezi alokační a inicializační etapou objektu natolik silná, že nelze objekt pouze alokovat a už neinicializovat. Podobně, není-li možné objekt řádně inicializovat, nedovolí jej překladač ani alokovat. Objektové programování
Konstruktor je velice užitečným členem třídy, protože garantuje datovou konzistenci objektů této třídy ihned poté, co byly tyto objekty vygenerovány. Konstruktor se pojí se začátkem životního cyklu objektu. Opakem konstruktoru je finalizér. Sémanticky je finalizér metoda, která provádí různé finalizační akce těsně před tím, než bude dotyčný objekt podroben destrukci. Zatímco konstruktor provází objekt na začátku jeho života, finalizér vstupuje do hry krátce před úplným koncem životního cyklu objektu. Pokud jste někdy programovali v jazyce C++, mohli byste poznamenat, že finalizér je pouze jiným termínem pro destruktor. Není tomu ovšem tak. Ačkoliv se nebudeme v této podkapitole pouštět do dlouhých vědeckých debat, rádi bychom alespoň ve stručnosti uvedli věci na pravou míru. Inu, pro rychlé srovnání destruktoru a finalizéru platí následující: • Destrukce objektů v jazyce C++ je ryze deterministická. To znamená, že kdykoliv je na ukazatel aplikován unární operátor delete, dochází k neprodlené aktivaci destruktoru cílového objektu a po zpracování destruktoru také k okamžité likvidaci objektu samotného.
Technologické programování
• Finalizace objektů v jazyce Visual Basic 2010 je nedeterministická a je plně v kompetenci správce paměti (GC). Vývojáři v tomto prostředí tedy nedovedou spolehlivě predikovat čas začetí finalizace konkrétního objektu. Jediné, co vědí, je skutečnost, že objekt bude finalizován poté, co jej správce paměti shledá nepotřebným. Když vezmeme do úvahy fakt, že likvidace objektů je v jazyce Visual Basic 2010 řízena strojem (správcem paměti), je zřejmé, že ji nemusíme explicitně startovat. I proto se ve specifikaci pro jazyk Visual Basic 2010 nenachází žádný operátor delete, ani jiný, funkčně ekvivalentní operátor. Řekli jsme, že finalizér realizuje finalizační akce. Co si pod tím ale máme představit? Ve všeobecnosti je finalizační akce každá operace, kterou je nutno provést těsně před tím, než dojde k likvidaci objektu jako takového. Uveďme několik typických praktických příkladů finalizačních akcí: • uvolnění (dealokace) zdrojů, které byly získány (alokovány) konstruktorem při stavbě objektu, • uvolnění jakýchkoliv jiných zdrojů, kterých vytvoření bylo v kompetenci daného objektu, • ukončení spojení s datovým poskytovatelem a odpojení se od datového zdroje, • ukončení spojení se sítí a síťovým portem počítače,
27
Visual Basic 2010 - praktické příklady • ukončení spojení s jinými hardwarovými porty počítače, • likvidace podobjektů (pakliže nějaké existují), • ukončení diagnosticko-monitorovacích služeb (platí zejména pro systémové služby). Prakticky si užití finalizéru předvedeme na třídě Atom. Objekty této třídy budou atomy, přičemž třída sama nám dovede v kterémkoliv okamžiku podat informaci o počtu žijících atomů. Public Class Atom 'Defi nice sdíleného datového členu třídy. Private Shared pocetAtomu As Integer 'Defi nice konstruktoru. Public Sub New() New pocetAtomu += 1 End Sub 'Defi nice fi nalizéru. Protected Overrides Sub Finalize() pocetAtomu -= 1 End Sub 'Defi nice sdílené metody. Public Shared Function ZjistitPocetAtomu() As Integer Return pocetAtomu End Function End Class Komentář k zdrojovému kódu jazyka Visual Basic 2010: Pokud máme rádi pozvolné začátky, tak snad neexistuje lepší praktický příklad, který by dovedl výstižněji demonstrovat vztahy mezi konstruktorem a finalizérem. Třídu Atom navrhujeme tak, abychom dovedli monitorovat životní cykly atomů, jež vytvoříme. Aby vše fungovalo správně, potřebujeme následující artefakty: • Soukromý sdílený datový člen pocetAtomu typu Integer. Tento datový člen bude odrážet aktuální počet žijících objektů třídy Atom. • Veřejně přístupný bezparametrický instanční konstruktor. Kdykoliv vznikne nový atom, spustí se konstruktor, který aktualizuje čítač celkového počtu atomů.
28
1. Objektové programování
Objektové programování
• Chráněný fi nalizér. Finalizér je v jazyce Visual Basic 2010 implementován jako finalizační metoda s identifikátorem Finalize. Jak si můžeme všimnout, syntakticky je finalizér bezparametrickou metodou s chráněnými (Protected) přístupovými právy. Navíc, v hlavičce finalizéru se nachází klíčové slovo Overrides, které indikuje skutečnost, že finalizační metoda ve třídě Atom překrývá stejnojmennou finalizační metodu bázové třídy Object z jmenného prostoru System. • Veřejně přístupná sdílená metoda pro zjištění počtu atomů. Tato metoda nám umožní kdykoliv získat skutečný počet žijících atomů čili objektů třídy Atom. Věci se stanou zajímavějšími, když kód hlavní metody Main upravíme podle následujícího vzoru: Sub Main() 'Vytvoření pole 10 atomů. Dim atomy(9) As Atom For mAtom = 0 To atomy.GetUpperBound(0) atomy(mAtom) = New Atom() Next Console.WriteLine("Vytvořené atomy: {0}.", Atom.ZjistitPocetAtomu()) Console.WriteLine("Likvidace 2 atomů.") atomy(0) = Nothing atomy(9) = Nothing Console.WriteLine("Provedena kolekce haldy.") Technologické programování
GC.Collect() 'Čekání na zpracování fi nalizérů atomů. GC.WaitForPendingFinalizers() Console.WriteLine() Console.WriteLine("Celkový počet atomů: {0}.", Atom.ZjistitPocetAtomu()) Console.WriteLine() 'Spuštění časového testu. For i = 1 To 10 Console.Title = "Uplynulý čas: " & i & " s." Threading.Thread.Sleep(1000) If i < 9 Then
29
Visual Basic 2010 - praktické příklady atomy(i) = Nothing Console.WriteLine("Likvidace atomu č. {0}.", i) End If Next 'Ukončení časového testu. Console.WriteLine() Console.WriteLine("Provedena kolekce haldy.") GC.Collect() GC.WaitForPendingFinalizers() Console.WriteLine() Console.WriteLine("Celkový počet atomů: {0}.", Atom.ZjistitPocetAtomu()) End Sub Komentář k zdrojovému kódu jazyka Visual Basic 2010: Esence praktické ukázky tkví v empirické analýze životních cyklů atomů. Postupujeme tak, že nejprve vytvoříme pole 10 atomů, a poté začneme pozvolna atomy likvidovat podle předem daného algoritmu. Abychom dovedli namalovat časovou křivku vyjadřující délku života jednotlivých atomů, sledujeme ve vymezených časových okamžicích jejich aktuální počet. Jak víme, atomy jsou pod kontrolou správce paměti, který je uvolňuje samočinně. Když ovšem potřebujeme věci malinko popohnat, musíme si pomoci explicitním voláním sdílené metody Collect správce paměti (GC). Tato akce správci paměti nařídí, aby provedl kolekci řízené haldy a vyhledal nepotřebné objekty. Naše atomy ovšem vyžadují explicitní finalizaci, což je pochopitelné vzhledem k tomu, že vzešly ze třídy, která explicitně definuje finalizér. Čekání na zpracování finalizérů nedosažitelných atomů obstará metoda WaitForPendingFinalizers správce paměti. Důležité: Zrušení spojení mezi prvkem pole (odkazovou proměnnou) a cílovým objektem (atomem) provádíme programovou cestou prostřednictvím přiřazení nulového odkazu (klíčové slovo Nothing) do požadované odkazové proměnné. Není těžké uhodnout, že nejdřív skončí svoji pouť dva atomy – první a poslední. Poté se rozeběhne časovač, který během 10 sekund zlikviduje i všechny zbývající atomy. (Podotkněme, že aktuální hodnota časovače se zobrazuje v záhlaví okna konzolové aplikace jazyka Visual Basic 2010.) Výstup programu uvádí obr. 1.2. na následující straně.
30