58
Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: [email protected] PRZYK£ADOWY ROZDZIA£ PRZYK£ADOWY ROZDZIA£ IDZ DO IDZ DO ZAMÓW DRUKOWANY KATALOG ZAMÓW DRUKOWANY KATALOG KATALOG KSI¥¯EK KATALOG KSI¥¯EK TWÓJ KOSZYK TWÓJ KOSZYK CENNIK I INFORMACJE CENNIK I INFORMACJE ZAMÓW INFORMACJE O NOWOCIACH ZAMÓW INFORMACJE O NOWOCIACH ZAMÓW CENNIK ZAMÓW CENNI K CZYTELNIA CZYTELNIA FRAGMENTY KSI¥¯EK ONLINE FRAGMENTY KSI¥¯EK ONLINE SPIS TRECI SPIS TRECI DODAJ DO KOSZYKA DODAJ DO KOSZYKA KATALOG ONLINE KATALOG ONLINE Visual Basic .NET. Ksiêga eksperta Autor: Paul Kimmel T³umaczenie: Krzysztof Jurczyk, Marek Pa³czyñski ISBN: 83-7197-771-9 Tytu³ orygina³u: Visual Basic .NET Unleashed Format: B5, stron: 682 Przyk³ady na ftp: 3044 kB Visual Basic przeszed³ generalny remont. Istnieje wiele powodów, dla których programici Visual Basica 6 powinni przesi¹æ siê na nowy Visual Basic .NET. Nale¿y do nich zaliczyæ chocia¿by formularze Web, mo¿liwoæ tworzenia aplikacji i us³ug WWW, strukturaln¹ obs³ugê wyj¹tków, prawdziwe programowanie zorientowane obiektowo czy te¿ wielow¹tkowoæ. „Visual Basic .NET. Ksiêga eksperta” zawiera dok³adne omówienie nowego jêzyka Visual Basic .NET, zunifikowanego rodowiska programowania Visual Studio IDE, programowania formularzy WWW, ADO.NET, us³ugi WWW, GDI+ i wiele innych. Visual Studio .NET jest rodowiskiem bardzo rozbudowanym i potê¿nym. Aby w pe³ni je wykorzystaæ, poznasz tak¿e sposoby tworzenia makr oraz znajdziesz omówienie modelu automatyzacji s³u¿¹cego do indywidualizacji zadañ i interfejsu IDE w Visual Studio. Ksi¹¿ka zawiera wiele przyk³adów wziêtych z praktyki programistycznej. Ksi¹¿ka omawia: • rodowisko programistyczne Visual Studio, korzystanie z SourceSafe • Jêzyk Visual Basic .NET, programowanie zorientowane obiektowo w VB .NET • Rozszerzanie rodowiska programistycznego za pomoc¹ makr • Zaawansowane programowanie w VB .NET: refleksje, przeci¹¿anie, programowane oparte na zdarzeniach, polimorfizm, definiowanie atrybutów • Tworzenie interfejsu u¿ytkownika (aplikacje konsolowe, aplikacje z interfejsem Windows) • Pisanie aplikacji wielow¹tkowych • Uruchamianie us³ug WWW (Web Services) „Visual Basic .NET. Ksiêga eksperta” jest doskona³ym podrêcznikiem dla wszystkich osób, dla których osi¹gniêcie wysokiej sprawnoci w pos³ugiwaniu siê jêzykiem Visual Basic stanowi podstawê kariery programistycznej. Niezale¿nie, od tego, czy u¿ywa³e poprzedniej wersji tego jêzyka, czy te¿ nie: jeli chcesz staæ siê ekspertem Visual Basica, trzymasz w rêku odpowiedni¹ ksi¹¿kê.

Visual Basic .NET. Księga eksperta

Embed Size (px)

DESCRIPTION

Visual Basic przeszedł generalny remont. Istnieje wiele powodów, dla których programiści Visual Basica 6 powinni przesiąść się na nowy Visual Basic .NET. Należy do nich zaliczyć chociażby formularze Web, możliwość tworzenia aplikacji i usług WWW, strukturalną obsługę wyjątków, prawdziwe programowanie zorientowane obiektowo czy też wielowątkowość."Visual Basic .NET. Księga eksperta" zawiera dokładne omówienie nowego języka Visual Basic .NET, zunifikowanego środowiska programowania Visual Studio IDE, programowania formularzy WWW, ADO.NET, usługi WWW, GDI+ i wiele innych.Visual Studio .NET jest środowiskiem bardzo rozbudowanym i potężnym. Aby w pełni je wykorzystać, poznasz także sposoby tworzenia makr oraz znajdziesz omówienie modelu automatyzacji służącego do indywidualizacji zadań i interfejsu IDE w Visual Studio. Książka zawiera wiele przykładów wziętych z praktyki programistycznej. Książka omawia: * Środowisko programistyczne Visual Studio, korzystanie z SourceSafe * Język Visual Basic .NET, programowanie zorientowane obiektowo w VB .NET * Rozszerzanie środowiska programistycznego za pomocą makr * Zaawansowane programowanie w VB .NET: refleksje, przeciążanie, programowane oparte na zdarzeniach, polimorfizm, definiowanie atrybutów * Tworzenie interfejsu użytkownika (aplikacje konsolowe, aplikacje z interfejsem Windows) * Pisanie aplikacji wielowątkowych * Uruchamianie usług WWW (Web Services)"Visual Basic .NET. Księga eksperta" jest doskonałym podręcznikiem dla wszystkich osób, dla których osiągnięcie wysokiej sprawności w posługiwaniu się językiem Visual Basic stanowi podstawę kariery programistycznej. Niezależnie, od tego, czy używałeś poprzedniej wersji tego języka, czy też nie: jeśli chcesz stać się ekspertem Visual Basica, trzymasz w ręku odpowiednią książkę.

Citation preview

Page 1: Visual Basic .NET. Księga eksperta

Wydawnictwo Helionul. Chopina 644-100 Gliwicetel. (32)230-98-63e-mail: [email protected]

PRZYK£ADOWY ROZDZIA£PRZYK£ADOWY ROZDZIA£

IDZ DOIDZ DO

ZAMÓW DRUKOWANY KATALOGZAMÓW DRUKOWANY KATALOG

KATALOG KSI¥¯EKKATALOG KSI¥¯EK

TWÓJ KOSZYKTWÓJ KOSZYK

CENNIK I INFORMACJECENNIK I INFORMACJE

ZAMÓW INFORMACJEO NOWO�CIACH

ZAMÓW INFORMACJEO NOWO�CIACH

ZAMÓW CENNIKZAMÓW CENNIK

CZYTELNIACZYTELNIA

FRAGMENTY KSI¥¯EK ONLINEFRAGMENTY KSI¥¯EK ONLINE

SPIS TRE�CISPIS TRE�CI

DODAJ DO KOSZYKADODAJ DO KOSZYKA

KATALOG ONLINEKATALOG ONLINE

Visual Basic .NET.Ksiêga ekspertaAutor: Paul KimmelT³umaczenie: Krzysztof Jurczyk, Marek Pa³czyñskiISBN: 83-7197-771-9Tytu³ orygina³u: Visual Basic .NET UnleashedFormat: B5, stron: 682Przyk³ady na ftp: 3044 kB

Visual Basic przeszed³ generalny remont. Istnieje wiele powodów, dla których programi�ci Visual Basica 6 powinni przesi¹�æ siê na nowy Visual Basic .NET. Nale¿y do nich zaliczyæ chocia¿by formularze Web, mo¿liwo�æ tworzenia aplikacji i us³ug WWW, strukturaln¹ obs³ugê wyj¹tków, prawdziwe programowanie zorientowane obiektowo czy te¿ wielow¹tkowo�æ.

„Visual Basic .NET. Ksiêga eksperta” zawiera dok³adne omówienie nowego jêzyka Visual Basic .NET, zunifikowanego �rodowiska programowania Visual Studio IDE, programowania formularzy WWW, ADO.NET, us³ugi WWW, GDI+ i wiele innych.

Visual Studio .NET jest �rodowiskiem bardzo rozbudowanym i potê¿nym. Aby w pe³ni je wykorzystaæ, poznasz tak¿e sposoby tworzenia makr oraz znajdziesz omówienie modelu automatyzacji s³u¿¹cego do indywidualizacji zadañ i interfejsu IDE w Visual Studio. Ksi¹¿ka zawiera wiele przyk³adów wziêtych z praktyki programistycznej. Ksi¹¿ka omawia:

• �rodowisko programistyczne Visual Studio, korzystanie z SourceSafe • Jêzyk Visual Basic .NET, programowanie zorientowane obiektowo w VB .NET • Rozszerzanie �rodowiska programistycznego za pomoc¹ makr • Zaawansowane programowanie w VB .NET: refleksje, przeci¹¿anie, programowane oparte na zdarzeniach, polimorfizm, definiowanie atrybutów • Tworzenie interfejsu u¿ytkownika (aplikacje konsolowe, aplikacje z interfejsem Windows) • Pisanie aplikacji wielow¹tkowych • Uruchamianie us³ug WWW (Web Services)

„Visual Basic .NET. Ksiêga eksperta” jest doskona³ym podrêcznikiem dla wszystkich osób, dla których osi¹gniêcie wysokiej sprawno�ci w pos³ugiwaniu siê jêzykiem Visual Basic stanowi podstawê kariery programistycznej. Niezale¿nie, od tego, czy u¿ywa³e� poprzedniej wersji tego jêzyka, czy te¿ nie: je�li chcesz staæ siê ekspertem Visual Basica, trzymasz w rêku odpowiedni¹ ksi¹¿kê.

Page 2: Visual Basic .NET. Księga eksperta

���������

�������� ��

������

����������� �������������� ��� �������� ���������������������������������������

��������������������������������������� ������!�������Profile użytkownika.................................................................................................................. 30Tworzenie projektu .................................................................................................................. 31Pliki i katalogi projektu ....................................................................................................... 31Dodawanie projektu do kontroli kodu źródłowego ................................................................. 33

Kompilacja projektów............................................................................................................... 35Korzystanie z menedżera konfiguracji................................................................................... 36Właściwości wspólne .......................................................................................................... 36Opcje konfiguracyjne .......................................................................................................... 38Debug Build ....................................................................................................................... 38Release Build ..................................................................................................................... 38Kompilacje typu Command-Line oraz korzystanie z Make File ............................................... 39

Organizacja kodu źródłowego formularza ................................................................................... 39Przełączanie się pomiędzy widokiem kodu a widokiem obiektów............................................ 42Przestrzenie nazw............................................................................................................... 43Skracanie kodu................................................................................................................... 44Dyrektywa #Region ............................................................................................................ 45Edytowanie kodu i cechy ułatwiające tworzenie dokumentacji ................................................ 45

Konfiguracja opcji IDE............................................................................................................. 48Opcje środowiska ............................................................................................................... 49Opcje kontroli kodu źródłowego........................................................................................... 49Opcje edytora tekstu ........................................................................................................... 49Opcje projektanta formularzy (Windows Forms Designer)...................................................... 50Opcje analizatora ................................................................................................................ 50Opcje narzędzi bazy danych ................................................................................................ 50Opcje debugowania............................................................................................................. 50Opcje projektanta HTML .................................................................................................... 51Opcje projektu.................................................................................................................... 51Opcje projektanta XML ...................................................................................................... 51

Proces debugowania w nowym IDE........................................................................................... 51Podstawowe klawisze skrótów podczas debugowania............................................................. 52Strukturalna obsługa wyjątków ............................................................................................ 53

Przegląd Szablonów Projektów.................................................................................................. 53Windows Application.......................................................................................................... 53Class Library...................................................................................................................... 54

Page 3: Visual Basic .NET. Księga eksperta

6 Visual Basic .NET. Księga eksperta

Windows Control Library .................................................................................................... 55ASP.NET Web Applications ................................................................................................ 55ASP.NET Web Service ....................................................................................................... 57Web Control Library ........................................................................................................... 58Empty Project .................................................................................................................... 58Empty Web Project............................................................................................................. 58New Project in Existing Folder............................................................................................. 58Projekty w wersji Enterprise ................................................................................................ 58

Technologia IntelliSense ........................................................................................................... 60Składowe klas..................................................................................................................... 60Informacja o parametrach.................................................................................................... 60Szybka podpowiedź ............................................................................................................ 60Dokańczanie wyrazów ........................................................................................................ 60Cechy IntelliSense specyficzne dla VB ................................................................................. 61

Korzystanie z widoków............................................................................................................. 61Solution Explorer................................................................................................................ 61Class View......................................................................................................................... 62Server Explorer................................................................................................................... 62Resource View ................................................................................................................... 63Properties Window ............................................................................................................. 63Toolbox ............................................................................................................................. 63Pendind Check-ins .............................................................................................................. 63Web Browser ..................................................................................................................... 63Inne okna........................................................................................................................... 64

Dokumentacja.......................................................................................................................... 67Podsumowanie......................................................................................................................... 67

�����������"��������#���� $�Rozszerzenia plików................................................................................................................. 69Grupy Visual Basic jako rozwiązania.................................................................................... 69Nowe rozszerzenia plików źródłowych ................................................................................. 69

Przestrzenie nazw..................................................................................................................... 71Referencje ............................................................................................................................... 72Dyrektywy Option.................................................................................................................... 72Option Explicit ................................................................................................................... 72Option Compare ................................................................................................................. 74Option Strict....................................................................................................................... 74Moduł Option Private.......................................................................................................... 75Option Base ....................................................................................................................... 76

Typy danych............................................................................................................................ 76Typy Object ....................................................................................................................... 77Typy całkowite ................................................................................................................... 80Typy niecałkowite............................................................................................................... 81Typ Char ........................................................................................................................... 85Typ String.......................................................................................................................... 86Typ Boolean....................................................................................................................... 89Typ DateTime .................................................................................................................... 91

Deklaracje zmiennych............................................................................................................... 94Deklarowanie i inicjowanie pojedynczej zmiennej ................................................................. 95Deklaracje wielu zmiennych jednocześnie............................................................................. 96

Page 4: Visual Basic .NET. Księga eksperta

Spis treści 7

Inicjowanie wielu zmiennych jednocześnie ........................................................................... 97Definiowanie stałych........................................................................................................... 98Tworzenie egzemplarzy obiektów ........................................................................................ 98Listy inicjujące zmienne ...................................................................................................... 99

Operatory ................................................................................................................................ 99Funkcje konwersji typów ........................................................................................................ 101Zmiany zasięgu zmiennych w VB .NET................................................................................... 103Instrukcje sterowania pracą programu ...................................................................................... 103Tablice i kolekcje ................................................................................................................... 104Tablice o określonych granicach......................................................................................... 105Tablice N-wymiarowe....................................................................................................... 105Modyfikacja rozmiarów tablic............................................................................................ 106Zwracanie tablic przez funkcje........................................................................................... 106Tablice jako podklasy System.Array................................................................................... 107Abstrakcyjne typy danych ................................................................................................. 107

Strukturalna obsługa wyjątków................................................................................................ 109Korzystanie ze słów zastrzeżonych w Visual Basic .NET........................................................... 110Kompatybilność pomiędzy aplikacjami VB6 a VB .NET ........................................................... 110Microsoft.VisualBasic ....................................................................................................... 110Elementy programowania VB6 zmienione w Visual Basic .NET........................................... 111

Podsumowanie....................................................................................................................... 111

���������%�&�����������'��#��������� ������(�����)*+��%Deklarowanie i inicjowanie zmiennych..................................................................................... 113Inicjowanie zmiennych...................................................................................................... 114Deklarowanie i inicjowanie zmiennych w pojedynczej instrukcji........................................... 116Deklarowanie zmiennych tuż przed ich pierwszym użyciem ................................................. 116Deklarowanie zmiennych o jak najmniejszym zasięgu.......................................................... 116Korzystanie z refaktoringu: zamiana zmiennych tymczasowych na kwerendy ........................ 117

Praca z zasięgiem blokowym................................................................................................... 119Zmienne statyczne.................................................................................................................. 120Używanie zmiennych statycznych ...................................................................................... 120Zmienne statyczne a pamięć .............................................................................................. 121

Korzystanie z tablic ................................................................................................................ 121Tablice są instancjami klasy System.Array .......................................................................... 121Deklarowanie tablic .......................................................................................................... 122Korzystanie z metod tablicowych ....................................................................................... 122Tablice wielowymiarowe................................................................................................... 123

Praca z abstrakcyjnymi typami danych..................................................................................... 125Składowe klasy ArrayList.................................................................................................. 126Używanie ArrayList .......................................................................................................... 127HashTable........................................................................................................................ 128SortedList ........................................................................................................................ 129Queue.............................................................................................................................. 130Podsumowanie Abstrakcyjnych Typów Danych .................................................................. 130

Przesłanianie zmiennych ......................................................................................................... 131Funkcje i podprogramy ........................................................................................................... 132Definiowanie struktur ............................................................................................................. 132

Page 5: Visual Basic .NET. Księga eksperta

8 Visual Basic .NET. Księga eksperta

Używanie obiektów ................................................................................................................ 132Co to jest konstruktor? ...................................................................................................... 133Konstruktory sparametryzowane........................................................................................ 134Destruktory ...................................................................................................................... 134

Obsługa wyjątków.................................................................................................................. 135Try...Catch....................................................................................................................... 135Try...Finally ..................................................................................................................... 139

Podsumowanie....................................................................................................................... 140

���������,�-������������������ ������!����� �,�Automatyzacja zadań powtarzających się ................................................................................. 142Przykład: nagrywanie makra .............................................................................................. 142Podgląd zarejestrowanego makra........................................................................................ 143Edycja makra tymczasowego............................................................................................. 144Uruchamianie makra ......................................................................................................... 148Przypisywanie klawiszy skrótu do makra ............................................................................ 149Dodawanie klawisza makra do paska narzędziowego ........................................................... 149

Korzystanie z Eksploratora Makr ............................................................................................. 151Eksport makra........................................................................................................................ 151Makra włączające i wyłączające pułapki ............................................................................. 151Wysyłanie informacji do okna wyjściowego Output............................................................. 153Eksportowanie modułów makra ......................................................................................... 155Importowanie modułów makra........................................................................................... 155

Korzystanie z Macros IDE ...................................................................................................... 155Bezpieczeństwo makr........................................................................................................ 156Współdzielenie makr......................................................................................................... 156

Tworzenie projektu makra ...................................................................................................... 156Obsługa Visual Studio poprzez okno Command........................................................................ 158Odpowiadanie na zdarzenia IDE.............................................................................................. 158Dostosowanie Visual Studio do własnych wymagań .................................................................. 160Ogólny opis Extensibility Object Model.............................................................................. 161Ogólny opis Project-Neutral Extensibility Object Model....................................................... 165

Tworzenie przystawek............................................................................................................ 167Tworzenie projektu przystawki .......................................................................................... 168Rejestracja przystawek...................................................................................................... 172Dodawanie zachowań do przystawki .................................................................................. 173

Tworzenie kreatorów.............................................................................................................. 174Tworzenie pliku uruchomieniowego kreatora ...................................................................... 176Rejestracja biblioteki klas kreatora ..................................................................................... 176Testowanie kreatora.......................................................................................................... 176

Program Integracji Visual Studio ............................................................................................. 177Podsumowanie....................................................................................................................... 178

���������.�&�������/�0����������������� �1�Pisanie procedur..................................................................................................................... 179Pisanie procedur ............................................................................................................... 180Pisanie funkcji .................................................................................................................. 182

Definiowanie argumentów procedury ....................................................................................... 185Domyślne przekazywanie parametrów................................................................................ 186Korzystanie z parametrów opcjonalnych............................................................................. 190

Page 6: Visual Basic .NET. Księga eksperta

Spis treści 9

Definiowanie argumentów ParamArray .............................................................................. 193Redukowanie liczby parametrów........................................................................................ 194

Praca z rekurencją .................................................................................................................. 199Definiowanie procedur rekurencyjnych............................................................................... 199Zamiana rekurencji na algorytm nierekurencyjny................................................................. 199

Definiowanie struktur ............................................................................................................. 200Definiowanie pól i właściwości .......................................................................................... 201Dodawanie metod do struktur ............................................................................................ 202Implementowanie konstruktorów ....................................................................................... 203Definiowanie zdarzeń strukturalnych.................................................................................. 205Deklarowanie zmiennych w strukturze................................................................................ 207Ukrywanie informacji........................................................................................................ 208Argumenty struktur i typy zwracane ................................................................................... 208Cechy niedostępne dla struktur........................................................................................... 208

Korzystanie z typów wyliczeniowych....................................................................................... 209Podsumowanie....................................................................................................................... 210

������������ ����� ��� ����� ����� ��� ����� ��� ���

���������$��0������%Przestrzeń nazw Reflection...................................................................................................... 213Pakiety ............................................................................................................................ 214Manifest jako źródło informacji o zasobach......................................................................... 216Obiekt modułu.................................................................................................................. 216Obiekt File ....................................................................................................................... 219Właściwość Location ........................................................................................................ 221Właściwość EntryPoint ..................................................................................................... 221Właściwość GlobalAssemblyCache.................................................................................... 221Type................................................................................................................................ 221Wiązania.......................................................................................................................... 222Klasa MethodInfo ............................................................................................................. 227Klasa ParameterInfo ......................................................................................................... 228Klasa FieldInfo ................................................................................................................. 228Klasa PropertyInfo............................................................................................................ 228Klasa EventInfo................................................................................................................ 228

Tworzenie typów w trakcie działania aplikacji z wykorzystaniem refleksji .................................. 229Inne przypadki korzystania z refleksji....................................................................................... 232Lokalizacja ............................................................................................................................ 233Podsumowanie....................................................................................................................... 233

���������1�+������������%.Definiowanie klas................................................................................................................... 235Używanie specyfikatorów dostępu do klas .......................................................................... 237

Hermetyzacja i ukrywanie informacji ....................................................................................... 239Specyfikatory dostępu....................................................................................................... 240Praca z zasięgiem.............................................................................................................. 240

Dodawanie pól i właściwości................................................................................................... 240Hermetyzacja i właściwości ............................................................................................... 242Definiowanie właściwości indeksowanych.......................................................................... 243Korzystanie z modyfikatorów właściwości .......................................................................... 250

Page 7: Visual Basic .NET. Księga eksperta

10 Visual Basic .NET. Księga eksperta

Definiowanie właściwości współdzielonych........................................................................ 253Dodawanie atrybutów właściwości ..................................................................................... 253

Dodawanie metod do klas ....................................................................................................... 254Implementowanie konstruktorów i destruktorów.................................................................. 256Dodawanie funkcji i procedur do metod.............................................................................. 260Korzystanie z modyfikatorów metod .................................................................................. 263Korzystanie ze specyfikatorów dostępu............................................................................... 265

Dodawanie zdarzeń do klas ..................................................................................................... 266Definiowanie klas zagnieżdżonych........................................................................................... 267Zrozumienie celu korzystania z klas zagnieżdżonych ........................................................... 271Definiowanie klasy Signal ................................................................................................. 272Definiowanie abstrakcyjnej klasy bazowej Light.................................................................. 276Implementowanie świateł sygnalizacji ................................................................................ 276Podsumowanie programu TrafficLight................................................................................ 277

Tworzenie egzemplarzy klas.................................................................................................... 277Podsumowanie....................................................................................................................... 278

���������2�3�������������4�1�Rozumienie zdarzeń i procedur ich obsługi ............................................................................... 279Podstawowa delegacja: EventHandler................................................................................. 281Dołączanie wielu zdarzeń do jednej procedury obsługi ......................................................... 288

Tworzenie procedur obsługi zdarzeń w edytorze kodu............................................................... 290Pisanie procedur obsługi zdarzeń w edytorze kodu .............................................................. 293Przypisywanie procedur obsługi zdarzeń w trakcie pracy aplikacji......................................... 294

Tworzenie procedur obsługi zdarzeń w trakcie pracy aplikacji .................................................... 294Tworzenie procedur obsługi zdarzeń w WebForms Designer ...................................................... 296Deklarowanie i wywoływanie zdarzeń...................................................................................... 296Deklarowanie zdarzeń....................................................................................................... 298Generowanie zdarzeń........................................................................................................ 299Implementowanie procedur obsługi zdarzeń klasy................................................................ 300Implementowanie procedur obsługi zdarzeń współdzielonych............................................... 300Implementowanie procedur obsługi zdarzeń modułowych .................................................... 300Implementowanie procedur obsługi zdarzeń struktury .......................................................... 302Niedostępne właściwości zdarzeń....................................................................................... 303

Podsumowanie....................................................................................................................... 303

�����������3�'���%5.Używanie delegacji EventHandler............................................................................................ 306Korzystanie z argumentów obiektu EventHandler ................................................................ 306Korzystanie z argumentu EventHandler System.EventArgs................................................... 315

Przegląd składowych delegacji ................................................................................................ 315Definiowanie delegacji............................................................................................................ 317Deklarowanie procedur odpowiadających sygnaturom delegacji............................................ 317Inicjowanie delegacji......................................................................................................... 318Cel stosowania delegacji.................................................................................................... 318

Przekazywanie delegacji jako argumentów ............................................................................... 319Przegląd algorytmów sortowania i opis działania aplikacji.................................................... 320Algorytmy sortowania ....................................................................................................... 321Analiza działania aplikacji SortAlgorithms.......................................................................... 321Alternatywa dla typów proceduralnych ............................................................................... 326

Page 8: Visual Basic .NET. Księga eksperta

Spis treści 11

Delegacje grupowe ................................................................................................................. 327Metoda Combine .............................................................................................................. 329Korzystanie z delegacji grupowych..................................................................................... 329

Korzystanie z delegacji poza granicami projektu ....................................................................... 330Podsumowanie....................................................................................................................... 333

����������5�3����������������#��0��#%%.Podstawy dziedziczenia........................................................................................................... 335Co to jest dziedziczenie? ......................................................................................................... 336Podstawowa składnia dziedziczenia.................................................................................... 337Dziedziczenie w przykładach............................................................................................. 338Implementowanie właściwości, zdarzeń i metod w edytorze kodu......................................... 339Dziedziczenie pojedyncze a dziedziczenie wielokrotne......................................................... 342

Definiowanie klas, które muszą być dziedziczone...................................................................... 342Przykład wirtualnej klasy abstrakcyjnej .............................................................................. 343

Definiowanie klas, które nie mogą być dziedziczone.................................................................. 345Polimorfizm........................................................................................................................... 346Trzy rodzaje polimorfizmu ................................................................................................ 348Wywoływanie metod dziedziczonych ................................................................................. 350Przesłanianie metody klasy nadrzędnej ............................................................................... 350

Dynamiczne rzutowanie typów................................................................................................ 352Definiowanie interfejsów ........................................................................................................ 354Interfejsy a klasy .............................................................................................................. 354Definiowanie interfejsu ..................................................................................................... 355

Podsumowanie....................................................................................................................... 357

������������!����������6�������%.�Deklarowanie pól współdzielonych.......................................................................................... 359Definiowanie właściwości współdzielonych.............................................................................. 360Używanie metod współdzielonych ........................................................................................... 364Definiowanie konstruktorów współdzielonych .......................................................................... 369Konstruktory współdzielone i singletony............................................................................. 369Przykład konstruktora współdzielonego .............................................................................. 370

Implementowanie metod fabrycznych ...................................................................................... 375Przeciążanie składowych współdzielonych ............................................................................... 378Generowanie zdarzeń współdzielonych .................................................................................... 380Podsumowanie....................................................................................................................... 382

������������30�������������7��6� %2%Rola atrybutów....................................................................................................................... 384Czym są metadane? .......................................................................................................... 384Nazwy atrybutów ............................................................................................................. 390Elementy opisywane przez atrybuty.................................................................................... 391Opisywanie pakietu........................................................................................................... 391

Oznaczanie typów i składowych .............................................................................................. 393Dodawanie atrybutów typu................................................................................................ 393Dodawanie atrybutów metod ............................................................................................. 396Dodawanie atrybutów pól i własności ................................................................................. 399

Przeglądanie atrybutów za pomocą deasemblera MSIL.............................................................. 403Pozyskiwanie atrybutów za pomocą refleksji ............................................................................ 403

Page 9: Visual Basic .NET. Księga eksperta

12 Visual Basic .NET. Księga eksperta

Tworzenie atrybutów użytkownika .......................................................................................... 405Implementacja HelpAttribute ............................................................................................. 405Deklarowanie klasy atrybutu.............................................................................................. 405Określanie zasad użycia atrybutu — AttributeUsage ............................................................ 406Dziedziczenie z System.Attribute ....................................................................................... 407Implementowanie konstruktora .......................................................................................... 407Dodawanie nazwanych argumentów................................................................................... 408

Atrybutu komponentów .......................................................................................................... 408Atrybuty współpracy z COM................................................................................................... 409Podsumowanie....................................................................................................................... 409

������������ �!"���"�#� ����$%"!����! ������������������������������������������� &��

����������%��������������������,�%Podstawy aplikacji konsolowych.............................................................................................. 413Procedura Sub Main implementowana w module ................................................................. 414Procedura Sub Main implementowana w klasie ................................................................... 415Pozyskiwanie argumentów wierszy poleceń ........................................................................ 416

Klasa Console ........................................................................................................................ 420Odczyt i zapis w standardowych urządzeniach wejścia-wyjścia............................................. 421Zapis do urządzenia informacji o błędach............................................................................ 423Zmiana urządzenia informacji o błędach ............................................................................. 424

Implementacja programu FileSort ............................................................................................ 425Stosowanie TextReader ..................................................................................................... 426Stosowanie TextWriter ...................................................................................................... 430Pliki tymczasowe.............................................................................................................. 430Stosowanie interfejsu IEnumerator ..................................................................................... 431Sortowanie w ArrayList..................................................................................................... 432Implementowanie interfejsu IComparer .............................................................................. 432

Przestrzenie nazw aplikacji konsolowych.................................................................................. 433Wielowątkowość w aplikacji konsolowej.................................................................................. 433Debugowanie aplikacji konsolowych........................................................................................ 436Ustalanie argumentów wiersza poleceń za pomocą IDE ....................................................... 436Przyłączanie debugera do uruchomionej aplikacji ................................................................ 436

Monitorowanie systemu plików ............................................................................................... 439Podsumowanie....................................................................................................................... 440

����������,���������������8���� ,,�Przetwarzanie asynchroniczne bez udziału wątków.................................................................... 442Stosowanie timera............................................................................................................. 442Zdarzenie Application.Idle................................................................................................. 442

Lekkie wątki — pule wątków .................................................................................................. 444Czym jest pula wątków?.................................................................................................... 444Jak działa pula wątków?.................................................................................................... 445Stosowanie puli wątków.................................................................................................... 445Synchronizacja — WaitHandle .......................................................................................... 449Synchronizacja z wykorzystaniem klasy Monitor................................................................. 455

Wielowątkowość — waga ciężka ............................................................................................. 457Tworzenie i korzystanie z wątków...................................................................................... 457Przykład wątku................................................................................................................. 457

Page 10: Visual Basic .NET. Księga eksperta

Spis treści 13

Dołączanie atrybutu ThreadStatic ............................................................................................ 459Wielowątkowość a formularze Windows .................................................................................. 461Strategie wielowątkowości dla formularzy Windows............................................................ 462Invoke i wywołania synchroniczne ..................................................................................... 462Wywołania asynchroniczne — BeginInvoke i EndInvoke..................................................... 463

Podsumowanie....................................................................................................................... 466

����������.�!���������0��#������� ������,$1Przegląd przestrzeni nazw Forms............................................................................................. 467Klasy przestrzeni nazw Forms............................................................................................ 468Interfejsy przestrzeni nazw Forms...................................................................................... 478Struktury przestrzeni nazw Forms ...................................................................................... 479Delegacje przestrzeni nazw Forms...................................................................................... 480Wyliczenia przestrzeni nazw Forms.................................................................................... 481

Przegląd przestrzeni nazw System.Drawing .............................................................................. 482Klasy przestrzeni nazw System.Drawing............................................................................. 482Struktury przestrzeni nazw System.Drawing........................................................................ 489

Klasa Form............................................................................................................................ 489Powoływanie obiektu formularza ....................................................................................... 490Projektowanie interfejsu użytkownika................................................................................. 491Dynamiczne tworzenie kontrolek ....................................................................................... 493Procedury obsługi zdarzeń dynamicznie tworzonych kontrolek ............................................. 494Wyszukiwanie aktywnego formularza................................................................................. 494Dołączanie kodu do formularzy.......................................................................................... 494

Tworzenie formularzy użytkownika za pomocą GDI+ ............................................................... 495Podsumowanie....................................................................................................................... 495

����������$�&���������������0�����9���������,�1Rozmieszczanie kontrolek ....................................................................................................... 497Kotwiczenie kontrolek....................................................................................................... 498Dokowanie kontrolek ........................................................................................................ 499Zachowanie marginesu kontrolek ....................................................................................... 499Ustalanie położenia i rozmiaru ........................................................................................... 499

Praca z Menu......................................................................................................................... 500Definiowanie MainMenu i ContextMenu ............................................................................ 500Dołączanie kodu menu...................................................................................................... 501Różnice pomiędzy MainMenu i ContextMenu..................................................................... 503Dynamiczne dodawanie pozycji menu ................................................................................ 504

Zaawansowane techniki projektowania formularzy .................................................................... 507Własność Form.AutoScale................................................................................................. 507Automatyczne przewijanie................................................................................................. 507Rozmiar AutoScrollMargin................................................................................................ 508Stosowanie obiektu CreateParams...................................................................................... 508

Czym zajmują się klasy Component i Control ........................................................................... 510Klasa Component ............................................................................................................. 510Klasa Control ................................................................................................................... 511

Dynamiczne dodawanie kontrolek............................................................................................ 512Kontrolki użytkownika — UserControls ................................................................................... 513Wprowadzanie kontrolek do kontrolki użytkownika............................................................. 513Zdarzenia w kontrolkach użytkownika ................................................................................ 514

Page 11: Visual Basic .NET. Księga eksperta

14 Visual Basic .NET. Księga eksperta

Kod w kontrolkach użytkownika ........................................................................................ 516Umieszczanie kontrolki użytkownika w Visual Studio .NET ................................................ 516Przypisywanie kontrolce bitmapy pojawiającej się oknie narzędziowym................................ 517

Tworzenie własnych kontrolek ................................................................................................ 517Tworzenie niewidocznych komponentów............................................................................ 518Określanie domyślnego zdarzenia....................................................................................... 519

Podsumowanie....................................................................................................................... 520

����������1�&��'��#��������:3;<.��Podstawy GDI+ ..................................................................................................................... 521Stosowanie obiektów Graphics........................................................................................... 522Podstawowe klasy związane z rysowaniem ......................................................................... 524Proste operacje z wykorzystaniem GDI+............................................................................. 525Kreślenie figur płaskich i tekstu ......................................................................................... 526

Zaawansowane metody graficzne............................................................................................. 530Kreślenie krzywych .......................................................................................................... 530Kreślenie skomplikowanych krzywych — krzywe Bézier..................................................... 531Ścieżka graficzna — klasa GraphicsPath............................................................................. 532Klasa Region .................................................................................................................... 537Formularze o niestandardowych kształtach.......................................................................... 537Klasa Icon........................................................................................................................ 540Przestrzeń nazw Imaging ................................................................................................... 540

Grafika użytkownika w formularzach Windows ........................................................................ 541Drukowanie grafiki................................................................................................................. 542Podsumowanie....................................................................................................................... 543

�������������� ������'�(�����)���*�+�,������������������������������ -&-

����������2�!������������#��#�����������'� �= 7�!�>���? .,1Przegląd usług Web Services ................................................................................................... 547Wyszukiwanie usług Web Services za pomocą UDDI................................................................ 549uddi.microsoft.com........................................................................................................... 550Lokalne usługi Web Services ............................................................................................. 550Cztery aspekty pracy z Web Services.................................................................................. 551

Wywoływanie usług WWW.................................................................................................... 552Odwołania do WebServices ............................................................................................... 552Aplikacje formularzy Windows.......................................................................................... 554Aplikacje formularzy WWW ............................................................................................. 555

Implementowanie usług WWW............................................................................................... 556Plik global.asax ................................................................................................................ 556Plik web.config................................................................................................................. 557Plik disco ......................................................................................................................... 559Plik .asmx ........................................................................................................................ 560Kiedy usługi Web Servcies mogą okazać się przydatne ........................................................ 561Tworzenie usługi Web Service ........................................................................................... 562

Wybór metody dostępu sieciowego .......................................................................................... 566Zarządzanie informacjami stanu............................................................................................... 567Obsługa i generowanie wyjątków w usługach Web Services....................................................... 569

Page 12: Visual Basic .NET. Księga eksperta

Spis treści 15

Debugowanie usług Web Services............................................................................................ 570Zintegrowane debugowanie ............................................................................................... 571Uruchamianie bez debugowania ......................................................................................... 571Uruchamianie w przeglądarce ............................................................................................ 571

Kompilowanie i rozpowszechnianie projektów sieciowych......................................................... 572Podsumowanie....................................................................................................................... 573

������������&��'��#����������������!&)*+.1.Formularze WWW................................................................................................................. 576Okno projektowania formularzy WWW.............................................................................. 576Kod formularzy WWW..................................................................................................... 578Kompilowanie i uruchamianie aplikacji ASP.NET............................................................... 580

Request i Response................................................................................................................. 580ASP.NET i ADO.NET............................................................................................................ 581Baza danych przykładowych programów ............................................................................ 582Sortowanie danych w formularzu WWW............................................................................ 584Stronicowanie danych przy użyciu DataGrid ....................................................................... 586

Buforowanie danych wyjściowych........................................................................................... 587Dodawanie i usuwanie elementów bufora............................................................................ 590Deklarowanie terminu ważności elementów pamięci podręcznej ........................................... 591

Względy wydajnościowe......................................................................................................... 591Przygotowywanie kontrolek do wyświetlenia ............................................................................ 592Dynamiczne dodawanie kontrolek do strony............................................................................. 594Programowe dodawanie tekstu statycznego......................................................................... 594Modyfikowanie własności kontrolek przy użyciu kolekcji Attributes ..................................... 595Programowe dodawanie kontrolek LiteralControl ................................................................ 595Dodawanie kontrolek przy użyciu kontrolki PlaceHolder...................................................... 596Programowe dodawanie kontrolek prezentacji danych.......................................................... 597Wyposażanie kontrolek dynamicznych w procedury obsługi zdarzeń..................................... 598

Tworzenie własnych kontrolek WWW..................................................................................... 599Zapisywanie strony WWW jako kontrolki serwerowej ......................................................... 600Tworzenie własnej kontrolki użytkownika........................................................................... 606Tworzenie biblioteki kontrolek WWW ............................................................................... 607

Podsumowanie....................................................................................................................... 609

����������5�3������������4$��Źródło zdarzeń....................................................................................................................... 612Tworzenia źródła zdarzeń.................................................................................................. 612Usuwanie źródła zdarzeń................................................................................................... 614Pozyskiwanie tablicy dzienników zdarzeń........................................................................... 614Wyszukiwanie nazwy logu na podstawie nazwy źródła ........................................................ 615Usuwanie dziennika .......................................................................................................... 615

Dokonywanie wpisów do istniejącego dziennika ....................................................................... 615Własny dziennik zdarzeń......................................................................................................... 617Pobieranie zawartości dziennika zdarzeń .................................................................................. 618Czyszczenie dziennika zdarzeń................................................................................................ 620Powiadamianie o zdarzeniu ..................................................................................................... 620Zdalny dziennik zdarzeń ......................................................................................................... 621EventLogTraceListener........................................................................................................... 621Podsumowanie....................................................................................................................... 622

Page 13: Visual Basic .NET. Księga eksperta

16 Visual Basic .NET. Księga eksperta

.�� "!� ���������������������������������������������������������������������������������������������� /�0

3��������*�#�������'��#������� ($��#�������� ()*+ $�.Elementy usunięte z VB. NET................................................................................................. 625Zmiany w deklaracji i składni .................................................................................................. 627As Any ............................................................................................................................ 627Deklarowanie zmiennych................................................................................................... 627Numerowanie wierszy ....................................................................................................... 628

Zmiany zakresu widoczności zmiennych .................................................................................. 629Zmiany w deklaracji procedur ................................................................................................. 629Brak IsMissing ................................................................................................................. 630Wywoływanie procedur..................................................................................................... 630Przekazywanie własności przez referencję .......................................................................... 631ByVal — domyślny modyfikator argumentu ....................................................................... 632Argumenty ParamArray .................................................................................................... 632Modyfikator Static ............................................................................................................ 633

Zmiany we własnościach......................................................................................................... 633Ujednolicona deklaracja własności w Visual Basic .NET ..................................................... 634Let nie jest już obsługiwane............................................................................................... 634Własności domyślne nie mogą być współdzielone lub prywatne............................................ 634Własności domyślne muszą pobierać argumenty.................................................................. 634Argumenty własności nie mogą być przekazywane przez referencję...................................... 635

Zmiany zakresu tablic ............................................................................................................. 636Rozmiar tablicy może się zmienić, ale liczba wymiarów jest stała ......................................... 636

Zmiany w typach danych ........................................................................................................ 637Typ Currency................................................................................................................... 637Brak DefTyp.................................................................................................................... 637Konstrukcja Type zastąpiona przez Structure ...................................................................... 637Visual Basic .NET nie obsługuje ciągów tekstowych o ustalonej długości.............................. 638Zmiany w wartościach całkowitoliczbowych....................................................................... 638

Zmiany operatorów ................................................................................................................ 639Operatory równoważności i implikacji ................................................................................ 639And, Or, Xor i Not............................................................................................................ 639Szybkie oszacowanie......................................................................................................... 640

Zmiany w sterowaniu przebiegiem programu............................................................................ 640Wywołanie funkcji zamiast GoSub..................................................................................... 640Brak On ... GoSub i On ... Goto ......................................................................................... 642

Zmiany w klasach i interfejsach ............................................................................................... 643Parametryzowane konstruktory .......................................................................................... 643Brak Option Private Module .............................................................................................. 643Zmiany w interfejsach ....................................................................................................... 643

Zastąpione elementy programowania........................................................................................ 644Arcustangens (Atn) ........................................................................................................... 644Circle............................................................................................................................... 645Debug.Print i Debug.Assert ............................................................................................... 645DoEvents ......................................................................................................................... 645IsNull .............................................................................................................................. 645IsObject ........................................................................................................................... 645Line................................................................................................................................. 646

Page 14: Visual Basic .NET. Księga eksperta

Spis treści 17

LSet i RSet....................................................................................................................... 646MsgBox........................................................................................................................... 646Wend............................................................................................................................... 646

Elementy programowania obsługiwane w inny sposób............................................................... 647Calendar .......................................................................................................................... 647Date ................................................................................................................................ 647Empty zastąpiono przez Nothing ........................................................................................ 648Now ................................................................................................................................ 648Rnd i Round..................................................................................................................... 648PSet i Scale nie są obsługiwane w Visual Basic .NET.......................................................... 649Sgn i Sqr.......................................................................................................................... 649String............................................................................................................................... 649Time................................................................................................................................ 650VarType .......................................................................................................................... 650

Typ Variant zastąpiony przez Object........................................................................................ 650

!�������� $.�

Page 15: Visual Basic .NET. Księga eksperta

���������

�����������

Możliwość definiowania klas i tworzenia ich egzemplarzy (instancji) jest jedną z naj-ważniejszych cech każdego języka zorientowanego obiektowo. Aż do chwili obecnejVisual Basic nie obsługiwał w pełni obiektowości. Mimo że moduły w VB6 nazywanebyły modułami klas, tak naprawdę były interfejsami w sensie technologii COM (ang.Component Object Model). Oznacza to, że VB6 nie obsługiwał idiomu klasy; nie umoż-liwiał korzystania z innej bardzo pożytecznej cechy programowania obiektowego —dziedziczenia.

Zasadniczą różnicą pomiędzy interfejsami, a klasami jest dziedziczenie. Każda imple-mentacja interfejsu VB6 (modułu klasy) wymagała wprowadzenia wszystkich publicz-nych metod dla tego interfejsu. Klasy, w przeciwieństwie do interfejsu, obsługują dziedzi-czenie. Dziedziczenie oznacza, że mogą istnieć podklasy zawierające pola, właściwości,metody i zdarzenia klasy nadrzędnej. Tworząc nowe klasy, możesz je wykorzystywać dorozszerzania istniejących klas bazowych.

Zarówno zorientowane obiektowo klasy, jak i interfejsy COM udostępniają twórcomoprogramowania potężne marzędzia do tworzenia i zarządzania zaawansowanymi pro-jektami. Obie technologie są bardzo przydatne i obie zostały zaimplementowane w Vi-sual Basic .NET. Dodatkowo, Microsoft udoskonalił i poprawił interfejsy i opisy klasw celu zapobiegnięcia niejednoznaczności podczas ich stosowania. Obie technologie po-siadają odmienne zasady składni.

W tym rozdziale zostanie przedstawiona zmieniona składnia interfejsów oraz właściwościnowej definicji klasy, włączając w to dziedziczenie, polimorfizm, przeciążanie i prze-słanianie metod. Dodatkowo, rozdział ten zawiera kolejne przykłady wykorzystania ob-sługi wyjątków i wielowątkowości w Visual Basic .NET.

���������������

Klasa w Visual Basic .NET nie jest klasą VB6. Klasy VB6 są w VB .NET deklarowanei definiowane przy użyciu słowa kluczowego ���������. Klasy VB .NET są definiowa-nymi przez użytkownika typami agregacyjnymi, umożliwiającymi dziedziczenie. Różniąsię one od interfejsów COM, które są dokładnie tym, czym w VB6 były moduły klasy.

Page 16: Visual Basic .NET. Księga eksperta

236 Część II � Zaawansowane programowanie zorientowane obiektowo

Wszystkie klasy w Visual Basic .NET są definiowane w pliku .VB (w przeciwieństwiedo pliku .CLS), a w pliku takim może być zawarta jedna lub kilka klas. (Klasy, strukturyi moduły mogą być zgromadzone w jednym pliku). Podstawowa składnia klasy jest na-stępująca:

������������������������

Jeśli przez przypadek popełnisz błąd podczas deklarowania klasy, Visual Studio.NETIDE podkreśli linią falistą miejsce, w którym ten błąd występuje (zobacz rysunek 7.1)

���������Visual Studio .NET

IDE zaznacza linią

falistą miejsca

zawierające błąd

Najczęściej klasy poprzedzone są specyfikatorem dostępu ����, możesz jednak wyko-rzystać inne specyfikatory. W podrozdziale „Używanie specyfikatorów dostępu do klas”znajdziesz więcej informacji na ten temat.

Instrukcje ���� i ���� ���� tworzą jednostkę hermetyzacji dla klasy. Wszystkie skła-dowe klasy umieszczane są pomiędzy tymi instrukcjami.

Możesz dodawać dowolną liczbę pól, właściwości, metod i zdarzeń w celu zdefiniowaniaklasy, która ma spełniać określone wymagania w dziedzinie rozwiązania jakiegoś pro-blemu. Jakkolwiek liczba składowych w klasie może być dowolna, jednak przestrzeganienastępujących zasad w większości przypadków pozwoli na zachowanie przejrzystościw kodzie i uproszczenie tworzonych konstrukcji.

� Klasy powinny składać się z maksymalnie sześciu składowych publicznych,włączając w to właściwości i metody. Liczba składowych niepublicznych może byćwiększa, gdyż nie wpływają one na prostotę korzystania z klasy przez użytkownika.

� W ogólnym przypadku jakiekolwiek składowe niepubliczne powinny być chronionei wirtualne — posiadając modyfikator �����������.

Page 17: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 237

Pola, właściwości, zdarzenia wspólnie określane są mianem składowych. Termin skła-dowa odnosi się po prostu do czegoś, co zostało zdefiniowane jako część klasy.

Jak we wszystkich regułach, także i tu są wyjątki. Istnieje zasada „wystarczająco dobry”,wprowadzona przez Grady Boocha, mówiąca, że jeśli różnorodność oraz liczba składo-wych jest rozsądna i wystarczająca, to liczba ta jest wystarczająco dobra. W książce Ja-mesa Coplien „Zaawansowany C++” zostały przedstawione zaawansowane zagadnienia,które łamią ogólne zasady. Kolejnym przykładem wyjątku od opisanych powyżej regułsą klasy ze wszystkimi składowymi typu ������, jak np. klasa ���� w CLR.

Jak zostało wspomniane wcześniej, podstawowe wskazówki do definiowania klas są do-brym punktem startowym, istnieją jednak inne zasady i motywacje, którymi można siękierować podczas tworzenia klas. Na przykład technika refaktoringu „Zastosuj obiekt pa-rametryczny”, której zastosowanie ulepsza przekazywanie parametrów, wymaga utwo-rzenia dodatkowych klas.

������������ �������������������

W Visual Basic .NET występuje pięć specyfikatorów dostępu, opisanych w kolejnychpodrozdziałach.

������

Specyfikator dostępu ����, zastosowany na poziomie klasy, jest najczęściej używa-nym specyfikatorem. Klasy publiczne są to klasy, do których przewidziany jest dostępprzez każdego użytkownika. Specyfikator dostępu ���� występuje w kodzie po atry-butach i bezpośrednio przed słowem kluczowym ����. (W rozdziale 12., „Definiowa-nie atrybutów”, znajdziesz więcej informacji o atrybutach).

��� �����������������������

�����

Specyfikator �������� ma zastosowanie wyłącznie w klasach zagnieżdżonych. Klasyzagnieżdżone są są dostępne wyłącznie w danej klasie i w klasach potomnych. Nie mo-żesz zdefiniować składników egzemplarza klasy zagnieżdżonej z widocznością większąniż definicja klasy.

Definicja zagnieżdżonej klasy �������� ���� przedstawia się następująco:

��� �������������� ��������� �������������� ����������������������������

Klasa ����������� zawiera zagnieżdżoną klasę �������� ����. ����������� możeimplementować egzemplarze �������� ����, a klasy dziedziczące z ����������� mo-gą deklarować i tworzyć egzemplarze zagnieżdżonej klasy �������� ����.

Page 18: Visual Basic .NET. Księga eksperta

238 Część II � Zaawansowane programowanie zorientowane obiektowo

��� �

Klasy zaprzyjaźnione są dostępne wyłącznie w programie, w którym zostały zdefinio-wane. Jeśli dodasz specyfikator dostępu ������ do definicji klasy, egzemplarze tej klasymogą być tworzone wyłącznie w tym samym programie.

Załóżmy, że mamy bibliotekę klas z klasą o trybie dostępu ������ o nazwie ������ ����.Moglibyśmy utworzyć egzemplarze tej klasy w bibliotece klas, lecz nie możemy uczynićtego z poziomu użytkownika tej biblioteki. Można zatem powiedzieć, że ������ ���� jestwyłącznie do użytku wewnętrznego. Oto przykład:

����������������������������� �������������� ����������������������������������� ���������������������������

Korzystaj ze specyfikatora dostępu ������, gdy chcesz utworzyć klasę zawierającą detaleimplementacyjne biblioteki klas lub jakiejś innej aplikacji, uniemożliwiając tym samymdostęp do takiej klasy użytkownikom danej aplikacji.

��������� �

Klasy �������� ������ reprezentują połączenie specyfikatorów �������� i ������.Klasy chronione muszą być zagnieżdżone; z tego względu klasy �������� ������ rów-nież muszą być zagnieżdżone. Przykład pokazuje zagnieżdżoną klasę �������� ������:

��� �������������� ���������

������ ��������������������� ���������������� ����������������������������������������������������������

���������

Klasy ��������������� są najczęściej wykorzystywane jako klasy realizacyjne dla klasy,która je zawiera. Metody definiowane w klasach zagnieżdżonych mogą być wywoływanepośrednio przez metody proxy zawierającej je klasy. Nie możesz zwrócić egzemplarza klasy�������� ������. Poniższy przykład, bazując na kodzie powyżej, jest więc niepoprawny:

��� �������������� ���������

������ ��������������������� ���������������� ����������������������������������������������������������

����� ���������� ������� ������� ������ ���������

�������� ����

���������

Page 19: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 239

Taka definicja funkcji spowoduje wystąpienie błędu, wyraz �������������� zostaniepodkreślony linią falistą, a w liście zadań pojawi się uwaga, że ��������� niewłaściwieudostępnia typ �������������� poza klasą ����������������������������.

�����

Specyfikator dostępu ������ ma zastosowanie wyłącznie w klasach zagnieżdżonych.Klasy zagnieżdżone ������ reprezentują szczegóły implementacyjne danej klasy. Gdypojawi się wewnętrzny problem, którego rozwiązanie jest bardziej złożone i wymagamocy, jakiej nie są w stanie zapewnić proste metody, definiuje się wówczas zagnież-dżoną klasę prywatną, która rozwiązuje ten problem. Przykład składni takiej klasy wy-gląda następująco:

��� ������������!�������!������������!����������������������������

Egzemplarze ������ ���� mogą być tworzone wyłącznie w egzemplarzach ���������.Cel korzystania z klasy prywatnej pojawia się wówczas, gdy mamy grupę metod i wła-ściwości i musimy przechować wiele egzemplarzy stanu każdego z tych obiektów. Róż-nica polega na tym, że nie chcemy, aby prywatne klasy zagnieżdżone były widoczne dlaużytkownika z zewnątrz.

Stosunkowo rzadko w swych aplikacjach będziesz wykorzystywał klasy chronione i pry-watne. Miej jednak na uwadze, że takie konstrukcje istnieją i w razie potrzeby nie bój sięich użyć

������������������������������

Hermetyzacja i ukrywanie informacji to zagadnienia bezpośrednio związane z progra-mowaniem zorientowanym obiektowo; mogłeś się z nimi spotkać już wcześniej. Termi-ny te dotyczą strategii programowania. Hermetyzacja literalnie oznacza dodawanieskładowych — pól, właściwości, metod i zdarzeń — do klas lub struktur. Ogólną zasa-dą jest to, że składowe dodaje się w tych miejscach, w których ich pojawienie się będzienajbardziej korzystne; to znaczy, gdzie będą mogły być najczęściej wykorzystywane lubzapewnią najlepsze udoskonalenie Twojej implementacji.

Konsument klasy jest to programista, który tworzy egzemplarze klasy. Twórca klasy(producent) może być również jednocześnie konsumentem.

Generalizer jest konsumentem, który będzie dziedziczył Twoje klasy.

Ukrywanie informacji jest to przypisywanie egzemplarzom określonych możliwościdostępu — mogą one być prywatne, chronione, publiczne i zaprzyjaźnione — w celuuwolnienia konsumentów lub generalizatorów od konieczności poznawania wszystkichskładowych danej klasy lub struktury. Ograniczając liczbę składowych klasy, którychmuszą się oni nauczyć — poprzez właśnie ukrycie informacji — tworzone klasy są ła-twiejsze do wykorzystania.

Page 20: Visual Basic .NET. Księga eksperta

240 Część II � Zaawansowane programowanie zorientowane obiektowo

����� �������������

Do ukrywania informacji wykorzystuje się następujące specyfikatory dostępu: ������,��������, ����, ������ oraz ������� (tymi ostatnimi zajmiemy się w dalszej częścirozdziału).

Kod klasy, który chcesz, aby był dostępny dla wszystkich, jest określany jako ����.Mówimy, że interfejs publiczny jest utworzony ze składowych publicznych. Składowe���� są implementowane dla potrzeb konsumentów klas. Gdy chcesz natomiast ukryćczęść informacji przed konsumentami publicznymi, jednak generalizatorzy mają miećmożliwość dostępu do tej informacji, zastosuj specyfikator dostępu ��������.

Składowe ������ służą wyłącznie do użytku wewnętrznego i mówimy, że zawierająszczegóły implementacyjne klasy. Ze szczegółami tymi jedynie producent klasy musibyć zaznajomiony.

Ostatnie ze specyfikatorów — ������ oraz �������� ������ — używane są w tychprzypadkach, w których klasy wykorzystywane są przez jednostki w tej samej aplikacji.Dostęp zaprzyjaźniony oznacza dostęp wyłącznie wewnątrzaplikacyjny. Na przykład,jeśli definiujesz bibliotekę klas, a użytkownicy z zewnątrz nie muszą lub nie powinnimieć dostępu do niektórych klas z tej biblioteki, oznaczasz je jako klasy ������.

Ogólna zasada jest taka, że należy wszystkie metody definiować jako ��������, chyba żemuszą być publiczne. Jeśli musisz ujawniać składowe, rób to bardzo rozsądnie i rozmyślnie.

��������������

Zagadnienie zasięgu zostało rozszerzone w Visual Basic .NET o zasięg blokowy. Nowereguły rządzące zasięgami zostały przedstawione w rozdziale 3., „Podstawy programo-wania w Visual Basic .NET”. Oprócz istniejących zasad i tych związanych z nowymzasięgiem blokowym, pojawił się nowy aspekt pracy — wsparcie dla dziedziczenia,wprowadzające dodatkowe względy, na które należy zwracać uwagę.

Gdy dziedziczysz z istniejącej klasy, Twoja nowa klasa posiada w swoim zasięguwszystkie z odziedziczonych składników — ��������, ������ i ����. Na szczęście,Visual Basic .NET nie pozwala na pojawienie się problemów z nazwami tych składni-ków; gdy wystąpi konflikt nazw, kompilator od razu o tym ostrzeże. Będziesz mógłwówczas zmienić nazwy konfliktowych składników, tworząc dwie oddzielne jednostki,lub wykorzystać słowo ������� do rozwiązania problemu. (Więcej informacji znaj-dziesz w podrozdziale „Korzystanie z modyfikatora Shadows”).

������������������������

Pole jest daną składową klasy. Pola mogą być składowymi typu ���� ���, jak np. !�"��#�� lub $���, lub też typu złożonego, czyli strukturą, wyliczeniem lub klasą. Właści-

wości są specjalnymi metodami, które ogólnie używane są do zapewnienia określonegodostępu do pól.

Page 21: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 241

Generalnie, pola są prywatnymi elementami klasy. Jeśli zapewniony jest dostęp do pola,jest to zrealizowane za pomocą właściwości. Z tego powodu pola są zazwyczaj prywat-ne, a właściwości — publiczne. Jednakże czasami pola nie są w ogóle udostępnione po-przez właściwości. Właściwości również nie zawsze reprezentują pole. Czasami repre-zentują one dane istniejące w bazie danych, rejestrze systemowym, pliku INI lub innąwartość, nie będącą bezpośrednio polem.

Motywacją tworzenia pól w postaci elementów prywatnych jest to, że nieograniczonydostęp do danych jest z natury ryzykowny. Rozważmy sposób przyrządzania sosu ho-lenderskiego. Jeśli ugotujesz żółtka zbyt szybko, dostaniesz jajecznicę. Jednak jeśli bę-dziesz powoli je gotował — kurek gazu w kuchence jest tu analogią do właściwościzmniejszającej lub zwiększającej ogień — otrzymasz prawidłową konsystencję sosu.

Kurek gazu jest metaforą na określenie metody właściwości. Pole reprezentuje ilość ciepła,a kurek — właściwość umożliwiającą jej zmianę. Osoba obsługująca kuchenkę nie jestuprawniona do zwiększenia ilości gazu poza określoną wartość. Wydruki 7.1 oraz 7.2przedstawiają dwie częściowe klasy reprezentujące kuchenkę oraz ustawianie ilości wy-pływającego gazu.

�� ������Klasa reprezentująca pole i właściwość dla ustawień temperatury kuchenki gazowej

�"#���� ����������!��$#�%#�����!�������&'������� ��(�����)#�*#������ ���'�������&'��������� ��(�����+#�,#�����-���.#�������/��������&'�������0#���������-��"1#""#�����������2���2���� ��(�����"$#�������(���� ������2����3�)11� ���2����45�1�"%#�������67�����&'�������45�)11��������������'����")#����������&'�������5�2���"*#�������(����8����9�������&'�������"+#������������",#".#���������'����"0#$1#����������

Na wydruku 7.1 widzimy zdefiniowane pole � �%������� jako $����, dostępne poprzezwłaściwość �%�������. Metoda właściwości &�� zwraca wartość pola, a ��� przypisujenową wartość do wartości pola. W wierszu 13. sprawdzany jest warunek, czy nie zostałyustawione niedopuszczalne wartości temperatury podczas tworzenia klasy. Przy jej wdra-żaniu metoda $��#'(����� zostanie wyłączona przez kompilator. Jeśli ����� byłaby uży-wana do kontroli rzeczywistej kuchenki, na pewno nie chciałbyś, aby temperatura mogłaprzekroczyć możliwości fizyczne kuchenki. W celu upewnienia się, że ustawienia tempe-ratury są prawidłowe podczas normalnej pracy urządzenia, w wierszu 13. skorzystanoz lustrzanego warunku !� w celu utrzymania temperatury w dopuszczalnych granicach.

Page 22: Visual Basic .NET. Księga eksperta

242 Część II � Zaawansowane programowanie zorientowane obiektowo

Powróćmy teraz do dyskusji poświęconej gramatyce języka. Zauważyłeś pewnie, że ko-rzysta się z prefiksu � przy nazwach pól, a opuszcza się je w nazwach właściwości.Zwróć uwagę również na zmianę sposobu deklaracji właściwości. W Visual Basic .NETdeklaracja właściwości jest pisana w pojedynczej strukturze bloku. Metody &�� oraz ���są blokami zagnieżdżonymi pomiędzy słowami ������� i �����������, które definiujągranice właściwości. (Przypomnij sobie, że w VB6 metody &�� i ��� były definiowanejako dwa oddzielne i niezależne bloki).

Wydruk 7.2 definiuje nową klasę o nazwie ��������%, która wykorzystuje różne technikido zapewnienia, że ustawienia przepustnicy mieszczą się w dopuszczalnych granicach.

�� ������Wykorzystanie wyliczenia w połączeniu z metodami właściwości w celu ograniczenia

wartości pola

�"#���� ���������������&�$#�%#������ ���&�����������������)#�����6����*#�����������+#����� ��������,#���������&�.#�0#�����!�������������� �����������������"1#""#������ ���'��������������� �����������������"$#"%#�����-��")#�������/��������������"*#���������-��"+#",#�����������2���2���� ������������������".#�����������������5�2���"0#�������(����8����9����2����$1#������������$"#$$#���������'����$%#$)#����������

Wyliczenie �������������# definiuje trzy dopuszczalne stany przepustnicy: !��� (biegjałowy), ����� (prędkość podróżna)� i (���������� (przyspieszanie). Jeśli wykorzy-stasz dyrektywę )����� ������ z tym wyliczeniem, klienci nie będą mogli ustawić nie-właściwej wartości �������. )����� ������ zapewni, że wszystkie wartości przekazy-wane do metody ��� właściwości ������� będą z zakresu �������������#, czyli !���, ���� lub (���������.

������������������������

Specyfikatory dostępu mogą być dodawane do każdego składnika w klasie. W największejliczbie przypadków, właściwości będą deklarowane jako składowe ���� klasy lub struk-tury. Oczywiście możesz zdefiniować właściwość z dowolnym innym specyfikatorem.

Page 23: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 243

Jedną ze strategii, gdzie stosuje się właściwości ��������, są klasy, które konsumencimogą czynić bardziej ogólnymi. Przez zadeklarowanie klasy z właściwościami chronio-nymi umożliwiasz generalizatorom podjęcie decyzji, czy awansować te właściwości dodostępu publicznego.

Specyfikator dostępu jest umieszczany przed słowem kluczowym �������. Jeśli nie dołą-czysz żadnego specyfikatora, składowe będą miały dostęp publiczny. Przykłady umiesz-czania specyfikatorów są zawarte w wydrukach 7.2 oraz 7.3.

Podawaj specyfikatory dostępu za każdym razem, gdy definiujesz składową. W rezultacieotrzymasz kod czytelny i jasny.

� �������������������������������!

Właściwości indeksowane są po prostu metodami właściwości posiadającymi obowiąz-kowy parametr. Parametr ten jest semantycznie traktowany jak indeks, ale po umieszcze-niu kodu w metodzie właściwości możesz robić z nim, co zechcesz. Poniżej zostanąomówione cechy właściwości i różnice pomiędzy właściwościami a właściwościami in-deksowanymi.

Podstawowa, zwykła właściwość posiada metody &�� oraz ���. Pierwsza z nich zacho-wuje się jak funkcja i jest niejawnie wywoływana, gdy właściwość zostaje użyta jakowartość prawostronna. Metoda ��� działa jak dane wykorzystywane jako wartości lewo-stronne i ustawia wartość odpowiadającą tej właściwości. W najprostszym wydaniu war-tość właściwości jest przechowywana w odpowiadającym jej polu. Zarówno właściwość,jak i pole są tego samego typu. Wydruk 7.2 demonstruje wykorzystanie prostej właściwo-ści, posiadającej metody &��, ��� oraz korzystającej z wartości pola. Zauważ, że definicjawłaściwości w wierszu 11. określa zwracany typ, lecz nie pobiera żadnych argumentów.

W przeciwieństwie do zwykłej właściwości, właściwość indeksowana posiada zdefi-niowany w nawiasach argument. Nie reprezentuje on wartości pola; jest raczej indek-sem do tej wartości. Konsekwencją obecności indeksu jest to, że odpowiadające polemusi być tablicą albo kolekcją, co zazwyczaj ma miejsce. Jednakże indeks może byćużywany do czegokolwiek, a parametr indeksowy nie musi być wartością liczbową.

Podstawową ideą stojącą za korzystaniem z właściwości indeksowanych jest to, że mo-żesz bezpiecznie opakować tablice i inne rodzaje kolekcji danych w metody właściwości.Cel tego działania jest taki sam, jak w przypadku opakowania pojedynczej danej w meto-dę właściwości: chcesz ochronić dane przed nadużywaniem. Na wydruku 7.3 zostałyzaprezentowane dwie właściwości indeksowane. Obie w rzeczywistości odnoszą się dotej samej tablicy, jednak odwołują się do niej na dwa różne sposoby.

�� ������Właściwości indeksowane

�"#���� �������6�������$#�%#�����!��������������� ���������5�:�;�����<��(=��<����>��?�)#�*#���(�7������� ���'���������������2���6����� ��6�������� ���������+#�����-���,#�������/��������������6�����

Page 24: Visual Basic .NET. Księga eksperta

244 Część II � Zaawansowane programowanie zorientowane obiektowo

�.#���������-���0#�����������2���2���� ���������"1#����������������6������5�2���""#������������"$#���������'����"%#")#�����!��������=�'���2���@��6����� ��6������<�A"*#�������2���B�=6����� ��6�������"+#",#�����(�&���&'� ���������5����������B�=6�����".#��������������B�=6������5����������@��6�����"0#��������������@��6������5���&'$1#���������$"#$$#������ ���'�����B�&�����2���B�&�� ���������� ��6������$%#�����-��$)#�������/����� �����6����@7���������<�B�&��$*#���������-��$+#$,#�����������2���2���� ��6�������$.#��������=�'�B�&���B�&��<�2����$0#������������%1#���������'����%"#%$#����������

W klasie !���*�� są zdefiniowane dwie właściwości indeksowane. Pierwsza z nich,o nazwie �����#�, rozpoczyna się w wierszu 5. i pobiera argument typu !���#��. Para-metr ten został nazwany !���* i literalnie funkcjonuje jako indeks do pola będącego ta-blicą łańcuchów, ������#�. Zwróć uwagę, w jaki sposób indeks ten jest wykorzystywa-ny w metodzie &�� w wierszach 6. – 8. i ��� w wierszach 9. – 11. Wiersze 7. i 11.demonstrują intuicyjne użycie indeksu i tablicy. Gdy egzemplarze właściwości !���*��oraz �����#� są użyte jako wartości prawostronne, wówczas wywoływana jest metoda&��. (Przykładem wykorzystania wartości prawostronnej jest instrukcja ��#+�*,!���*��'�����#�,-..). Metoda &�� ma zastosowanie, gdy !���*��'������� jest używana jakowartość lewostronna, jak w instrukcji !���*��'�����#�,/.�0�12����1.

Porównaj właściwości �����#� i 3�%��. W obu z nich argument pełni rolę indeksu. Wła-ściwości te zwracają wartości o określonych typach — �����# w przypadku �����#�(wiersz 5.) i !���#�� w przypadku 3�%�� (wiersz 22.). Z tego względu �����#� jest wła-ściwością indeksowaną typu �����#, a 3�%�� — właściwością indeksowaną typu !���"#��. 3�%�� pobiera jako argument łańcuch znaków, 3�%�, i zwraca pozycję tego łańcuchaw postaci indeksu odpowiadającej tablicy.

W wierszu 24. użyta jest metoda ������ o nazwie �����%'(����'!���*)�, która pobieratablicę i poszukiwany obiekt, a zwraca indeks tego obiektu w pobranej tablicy. W wier-szu 28. widzimy wywołanie ���� z wykorzystaniem bieżącego indeksu istniejącegoelementu (znalezionego za pomocą metody &��) oraz nowego indeksu reprezentowane-go przez ����. Element tablicy jest przenoszony ze starej pozycji do nowej. Poniższyfragment pokazuje, w jaki sposób możesz znaleźć właściwość 3�%�� użytą w kodzie:

(�&���6������� ��B�=�6��������6�������B�&����;�������5�"

Page 25: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 245

Gdy kod z wiersza 2. powyższego fragmentu zostanie wykonany, wartość pola — tabli-cy ������#� — jest równa 41$��15�12����15�1 ���16. Wartość na pozycji odpowiada-jącej nazwie „Jeden” jest przenoszona do indeksu 1 poprzez zamianę miejscami z war-tością elementu o indeksie 1.

����������������� ���������������� ������ ���

Korzyści ze stosowania właściwości indeksowanych są wielorakie. Oczywistą korzyściąjest to, że dane powinny być chronione przez metody bez wpływu na łatwość korzystaniaz nich. To, że dane są tablicami czy kolekcją, nie oznacza, że nie powinny być chronioneprzed niewłaściwym użyciem. Być może nie tak oczywistą zaletą jest również to, że bar-dziej złożone kolekcje danych mogą być łatwiejsze do użycia poprzez wskazanie, że wła-ściwość indeksowana ma być właściwością domyślną. (Więcej na ten temat za chwilę).

Wydruk 7.3 nie pokazuje ochrony danych przed nadużyciem. W naszej aplikacji musie-libyśmy zapewnić sprawdzanie, czy nie są używane niewłaściwe indeksy lub nazwy.Spójrzmy zatem, w których miejscach kodu możemy wprowadzić usprawnienia. Za-cznijmy od metody !���*��'3�%��.

Co stałoby się, gdybyśmy zażądali !���*��'3�%��,1 �����1.? Patrząc na istniejący kod— metoda (����'!���*)� zwróciłaby wartość 7-. Odpowiada nam takie rozwiązanie, po-zostawiamy więc 3�%���&�� bez zmian. Alternatywnie, moglibyśmy wygenerować wy-jątek, jeśli nazwa nie zostałaby znaleziona, jednak już teraz przy podaniu niewłaściwegoindeksu jest on podnoszony. W rezultacie ten fragment kodu jest w porządku.

Przyjrzyjmy się teraz metodzie ��� właściwości 3�%��. Nie ma w niej żadnego sprawdza-nia poprawności danych. Możemy sprawdzić, jak zachowuje się fragment kodu w przy-padku podania błędnych danych — jeśli użyty zostanie zły indeks, powinien wystąpićwyjątek. Faktycznie, !���*��'3�%��,1�����1.� 0� 8 podnosi �����%'!���*)�)�9��#�"�*�������. Wywołujący musi prawdopodobnie wiedzieć, że popełnił błąd, więc wystą-pienie wyjątku jest rozsądne. Z drugiej strony, informacja pokazująca się w momenciewystąpienia wyjątku jest zbyt ogólna i możemy uznać, że nas nie zadowala (zobacz ry-sunek 7.2).

���������Informacja pojawiająca sięw chwili wystąpienia

wyjątku przy niewłaściwym

użyciu indeksu w obiekcie

System.Array

Dla celów praktycznych, jeśli domyślna informacja o wyjątku zapewnia wystarczającąinformację, nie ma potrzeby pisania dodatkowego kodu do jego obsługi. Pamiętaj,że zawsze możesz obsłużyć wyjątek dodatkową procedurą.

Dla celów demonstracyjnych załóżmy, że domyślne zachowanie się wyjątku nie jest wy-starczające. Zaimplementujemy rozszerzoną jego obsługę, aby zapewnić konsumentomklasy !���*�� dodatkowe informacje.

Page 26: Visual Basic .NET. Księga eksperta

246 Część II � Zaawansowane programowanie zorientowane obiektowo

����������� ������ ��������������� �

Praktyczna modyfikacja tej metody ma na celu poinformowanie konsumenta, że użyłniewłaściwego indeksu. Będzie ona polegać na dodaniu we właściwości 3�%�� nowychfunkcji i modyfikacji metody ���. Na wydruku 7.4 przedstawiono zmiany dokonanew stosunku do kodu z wydruku 7.3.

�� ������Dodanie kodu umożliwiającego obsługę błędu wynikającego z niewłaściwego użycia indeksu

�"#���!������ �����2����6�������2���6����� ��6�������� ����������$#���/������6�����45����������-��9�=�������1��� ���A�%#������6�����35����������-��C''�������1���)#������� �����*#�+#���!����@!�����������2����������2���B�&�� ����������,#���2��������B�&���B�&����.#��������0#"1#���!����@!�����������2����������2���6����� ��6�������""#���67��B���2����6�����6�����������"$#���������=�B�=� ''�� ������� �'�����6�����D���E�������'�'��=��&�����F��&��"%#�������67")#�������"*#"+#���� ���'�����B�&�����2���B�&�� ���������� ��6������",#���-��".#�����/����� �����6����@7���������<�B�&��"0#�������-��$1#$"#���������2���2���� ��6�������$$#�����2��������B�&��$%#������=�'�B�&���B�&��<�2����$)#����������$*#�������'����

Zmiana w metodzie ��� właściwości 3�%�� polega na dodaniu wywołania do funkcji ��"������. Wiemy, że moglibyśmy sprawdzać poprawność indeksu bezpośrednio w meto-dzie ���, lecz we wcześniejszych rozdziałach omawialiśmy zalety i cel stosowania tech-niki refaktoringu „Wydzielanie metod”. W kodzie powyżej utworzyliśmy osobną funkcję�������� głównie po to, aby ��� była jak najkrótsza i najprostsza oraz aby mieć możli-wość wielokrotnego wykorzystania kodu ��������. Zastosowaliśmy przy tym dwieprzeciążone wersje ��������. Pierwsza z nich pobiera nazwę jako argument i wywołujedrugą wersję, pobierającą indeks. (Kolejną właściwością, gdzie moglibyśmy wprowa-dzić kod sprawdzający poprawność, jest �����#�, która wykorzystuje indeks całkowity)Aby uczynić kod bardziej czytelnym, zaimplementowaliśmy sprawdzanie wartości in-deksu w postaci metody �����!���* (wiersze 1. – 4.). Jeśli indeks jest niepoprawny, ge-nerowany jest wyjątek w wierszu 12.

Zauważ, że w kodzie nie ma komentarzy. Zastosowanie krótkich, zwięzłych i jasnychmetod czyni komentarze zbędnymi.

Page 27: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 247

����� �� ������������������������

Przypuśćmy, że chcemy wykorzystać kod wyrzucający wyjątek w wierszu 12. na wydru-ku 7.4 w kilku innych miejscach programu i być może nawet w innych klasach. Załóżmyrównież, że klasa !���*�� reprezentuje bardzo istotną i ważną część tworzonego systemu.

Więcej informacji na temat obsługi wyjątków znajdziesz w rozdziale 5., „Procedury,funkcje i struktury”, a na temat dziedziczenia — w rozdziale 10., „Dziedziczeniei polimorfizm”.

Moglibyśmy więc wprowadzić osobną klasę wyjątku, która hermetyzowałaby obsługębłędnych indeksów. Jest to możliwe poprzez utworzenie podklasy z istniejącej klasyobsługi wyjątku i rozszerzenie jej działania. Podejście to jest jak najbardziej prawidło-we i wielu programistów innych języków od lat wykorzystuje rozszerzone klasy wyjąt-ków w swoich aplikacjach.

Założyliśmy, że nasza klasa !���*�� jest istotna oraz że kod obsługi wyjątku wyrzuca-nego ze względu na niepoprawny indeks będzie wykorzystywany wielokrotnie. W po-mocy Visual Studio .NET możemy przeczytać, że jeśli chcemy utworzyć własną obsłu-gę wyjątków, powinniśmy skorzystać z klasy �����%'(�����������*�������.

Warunkiem wystąpienia błędu w naszej aplikacji jest przekazanie nieprawidłowego in-deksu do metody ��� właściwości 3�%�� klasy !���*��. Wyjątek jest generowany w wier-szu 12. wydruku 7.4, gdy sprawdzanie poprawności zakończy się niepowodzeniem. Takiezachowanie się kodu jest funkcjonalne, nie będziemy więc zmieniać organizacji w tymmiejscu. Zmienimy jednak zaangażowane w to obiekty, co prezentuje wydruk 7.5.

�� ������Kompletny wydruk klasy Indexed, zawierający nową klasę wyjątku

�"#���� �������6�������� �'�����$#���6�������� ''�� ������� �'�����%#�)#������ ����B�=���2������� ����������*#������������B�=������+#����������,#�.#������ ���������������=�� �'�������2���6����� ��6��������0#���������=�B�=�6�������� �'�����6�����D���E�������'�'��=��&�����F��&��"1#���������""#"$#����������"%#")#���� �������6������"*#"+#�����!��������������� ���������5�:�;�����<��(=��<����>��?",#".#���(�7������� ���'���������������2���6����� ��6�������� ��������"0#�����-��$1#�������/��������������6�����$"#���������-��$$#$%#�����������2���2���� ���������$)#����������������6������5�2���$*#������������$+#���������'����

Page 28: Visual Basic .NET. Księga eksperta

248 Część II � Zaawansowane programowanie zorientowane obiektowo

$,#$.#�����!��������=�'���2���@��6����� ��6������<�A$0#�������2���B�=6����� ��6�������%1#%"#�����(�&���&'� ���������5����������B�=6�����%$#��������������B�=6������5����������@��6�����%%#��������������@��6������5���&'%)#���������%*#%+#�����!������ �����2����6�������2���6����� ��6�������� ���������%,#�����/������6�����45����������-��9�=�������1��� ���A%.#��������6�����35����������-��C''�������1��%0#��������� ����)1#)"#�����!����@!�����������2����������2���B�&�� ���������)$#�����2��������B�&���B�&���)%#���������))#)*#�����!����@!�����������2����������2���6����� ��6�������)+#�����67��B���2����6�����6�����������),#�������G����=�B�=� ''�� ������� �'�����6�����D���E�������'�'��=��&�����F��&��).#�������6�������� �'���������=�� �'�����6�����)0#���������67*1#���������*"#*$#������ ���'�����B�&�����2���B�&�� ���������� ��6������*%#�����-��*)#�������/����� �����6����@7���������<�B�&��**#���������-��*+#*,#�����������2���2���� ��6�������*.#�������2��������B�&��*0#��������=�'�B�&���B�&��<�2����+1#������������+"#���������'����+$#+%#����������

Nowa klasa wyjątku jest zdefiniowana w pierwszych dwunastu wierszach. W wierszu 2.następuje wskazanie, że !���*���*������� dziedziczy z �����%'(�����������*�������.W żargonie programowania obiektowego mówi się, że jest to relacja !�(. Zunifikowanyjęzyk modelowania (ang. Unified Modeling Language — UML) określa dziedziczeniegeneralizacją. Mówimy, że !���*���*������� jest (�����������*�������.

!���*���*������� wprowadza przeciążonego konstruktora, który pobiera argument w po-staci łańcucha. Argument ten — wiersz 4. — stanie się częścią komunikatu naszego wy-jątku. W wierszu 5. używana jest zmienna ��+���, która odnosi się do klasy bazowej.��+��� jest dostępna podobnie jak zmienna ��, która jest referencją do samej siebie.W wierszu 8. definiowana jest metoda ������ �����*�������. Metoda ������, która two-rzy egzemplarz obiektu, jest nazywana metodą fabryczną. Metoda taka umożliwia zlokali-zowanie konstrukcji i zainicjowanie obiektu, zmniejszając potrzebę duplikowania kodutworzącego obiekt. I w końcu, procedura �������� zastępuje instrukcję z wiersza 12. wy-druku 7.4 na wywołanie do nowej metody fabrycznej, która tworzy i wyrzuca wyjątek.(Oryginalna instrukcja i jej zastąpienie są odpowiednio w wierszach 47. i 48. wydruku 7.3.).

Page 29: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 249

W chwili obecnej znasz już sposoby definiowania właściwości indeksowanych, doda-wania kodu sprawdzającego do metod właściwości oraz wiesz, jak wprowadzać noweklasy obsługi wyjątków. Jeśli dziedziczenie jest dla Ciebie pojęciem niejasnym, więcejinformacji na jego temat znajdziesz w rozdziale 10., „Dziedziczenie i polimorfizm”.

������� ���������������������� ���

Visual Basic .NET umożliwia korzystanie z właściwości domyślnych $�����, jednakw przeciwieństwie do VB6, w VB .NET jedynie właściwości indeksowane mogą byćdomyślne. Powód tego jest przedstawiony poniżej.

W VB6 korzystaliśmy z metody ��� podczas przypisywania referencji obiektu do zmien-nej obiektowej. Ponadto, jeśli element przypisywany był obiektem i nie było obecnej in-strukcji ���, VB6 wnioskował, że programista zamierza wykorzystać właściwość $�"����. Z tego powodu właściwości domyślne w VB6 nie musiały być właściwościamiindeksowanymi. Istnienie słowa kluczowego ��� stanowiło wystarczającą wskazówkędla kompilatora.

Visual Basic .NET nie wykorzystuje ��� do przypisywania obiektów. Z tego względuobecność obiektu, a nieobecność ��� nie są wystarczające dla kompilatora do określeniaTwoich zamiarów. W Visual Basic .NET podpowiedzią dla kompilatora, że chcemy sko-rzystać z właściwości $�����, jest obecność nawiasów przy nazwie obiektu. Wypływastąd wniosek, że w VB .NET wszystkie właściwości $����� muszą być właściwościamiindeksowanymi oraz możliwe jest posiadanie tylko jednej właściwości domyślnej.

Również w wersji obiektowej Pascala — Object Pascal — jedynie właściwościindeksowane mogą być domyślne. Obecność ��:���;< w tym języku jest wskazówkądla kompilatora, że programiście chodzi raczej o właściwość indeksowaną niżo przypisanie obiektu.

Jest możliwe — i bardzo prawdopodobne — że zmiana wprowadzona we właściwościachdomyślnych była dokonana częściowo pod wpływem Andersa Hejlsberga. Hejlsberg,w chwili obecnej Wyróżniony Inżynier (Distinguished Engineer) w Microsoft, byłkierownikiem sekcji architektów w firmie Borland i odegrał zasadniczą rolę w procesieimplementacji Delphi, stworzonego w Object Pascal. To nie jedyny wpływ ObjectPascala na elementy Visual Basic .NET. Nie można jednak powiedzieć, że VB .NETjest podobny do Pascala; należałoby raczej stwierdzić, że Visual Basic .NET jestjęzykiem rozwijającym się i Microsoft podjął bardzo mądrą decyzję, udoskonalając goz uwzględnieniem zalet innych języków.

Trzeba się przyzwyczaić do tego, że Visual Basic .NET jest produktem silniezmienionym i mocno udoskonalonym, jednak cały czas jest to Visual Basic.

Aby wskazać, że właściwość ma być właściwością domyślną, umieść słowo kluczowe$����� w wierszu, w którym definiujesz właściwość, bezpośrednio przed specyfikato-rem dostępu. Fragment wydruku 7.5 pokazuje sposób umieszczania słowa $�����,czyniąc �����#� właściwością domyślną:

(�7������� ���'���������������2���6����� ��6�������� ����������-������/��������������6�����������-��

Page 30: Visual Basic .NET. Księga eksperta

250 Część II � Zaawansowane programowanie zorientowane obiektowo

��������2���2���� ����������������������6������5�2������������������'����

Zakładając, że zadeklarowaliśmy egzemplarz !���*��, używając instrukcji $�%� !���*��")�:����(��3���!���*��, dostęp do właściwości �����#� jest możliwy poprzez wywołanie:

�������6������@�E� ����������"��

lub, ze względu na to, że �����#� jest właściwością domyślną:

�������6������@�E� ��"��

Podsumowując, właściwości domyślne muszą być indeksowane, możesz mieć tylko jednąwłaściwość domyślną w klasie i możesz wywoływać metody &�� i ��� właściwości do-myślnej, korzystając z zapisu pełnego lub skróconego.

"�������������� �������������������

Oprócz specyfikatorów dostępu, istnieją również specjalne modyfikatory, które wystę-pują tylko przy właściwościach. Są to modyfikatory 9���)��� oraz =����)���.

Właściwość tylko do odczytu (read-only) może być wykorzystywana wyłącznie jakoargument prawostronny. To znaczy, użytkownicy takiej metody mogą jedynie odczyty-wać właściwość, nie mogą jej modyfikować. Taka właściwość posiada więc jedyniemetodę &��. Konsumenci klasy mogą traktować właściwości 9���)��� jak stałe lub nie-zmienne dane, lecz należy pamiętać, że może istnieć mechanizm wewnętrzny w stosun-ku do obiektu, który może zmienić odpowiadającą właściwości wartość, mimo że kon-sument nie ma takiej możliwości.

Właściwość tylko do zapisu (write-only) może być modyfikowana przez konsumenta,ale nie może zostać przez niego oglądana. W nich zaimplementowana jest wyłączniemetoda ���.

Zewnętrzny blok właściwości jest w obu przypadkach identyczny, z wyjątkiem obecno-ści modyfikatora. Wewnętrznie właściwości 9���)��� posiadają jedynie metodę &��,a =����)��� — metodę ���.

����� ��� ������������������ ��

Przykładem właściwości tylko do odczytu może być zwracanie znacznika czasowegopodczas tworzenia obiektu. Ponieważ obiekt może być utworzony tylko raz — mimo żemożemy mieć wiele egzemplarzy klasy, to dany egzemplarz jest tworzony tylko jeden raz— nie ma sensu, aby umożliwiać konsumentom modyfikację daty utworzenia obiektu.

Jeśli musisz śledzić, jak długo dany obiekt istnieje, i chcesz mieć pewność, że konsu-menci nie zmienią znacznika czasu tego obiektu, możesz zdefiniować właściwość tylkodo odczytu ����� �%� i zainicjować ją w konstruktorze:

Page 31: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 251

��� ����B�=�����������B�=�������������&��5�B�=������

��!������������&�� ��(���

��� �/���@������'�������������&���� ��(�����-������/��������������&�������-��������'����

Zwróć uwagę na położenie modyfikatora 9���)���. Publiczna właściwość ����� �%�jest zdefiniowana jako tylko do odczytu i z tego powodu posiada wyłącznie blok &��.Konstruktor — ��� 3�� — inicjuje odpowiadające właściwości pole, � ����� �%�,w momencie wywołania konstruktora.

Innym przykładem wykorzystania właściwości tylko do odczytu jest pole obliczone. Je-śli właściwość nie posiada odpowiadającej wartości, a jej wartość jest gdzieś obliczana,nie ma sensu implementacja metody ���. Weźmy pod uwagę symetryczną właściwość������� �%�. Jeśli chcielibyśmy określić czas, jaki upłynął od uruchomienia aplikacji,moglibyśmy zwrócić ten czas jako wynik odjęcia od bieżącego czasu czas ����� �%�:

��� �/���@������'��������'�����&���� ����&��'����-������/�����(�����'A����� �����B�=<����������&��������-��������'����

Właściwość ������� �%� jest tylko do odczytu, gdyż odpowiadająca jej wartość jest ob-liczana dynamicznie za każdym razem, gdy właściwość jest wywoływana. Przy okazjiwidzimy wykorzystanie klasy �%�����, której implementacja w powyższym kodzieumożliwia bardzo dokładny pomiar czasu. Inną cechą kodu jest wywołanie współdzie-lonej metody $���'��>����������. Visual Basic .NET nie zezwala jeszcze na przecią-żanie operatorów, więc zaimplementowane zostały specjalne metody z prefiksem ��>w miejscach, gdzie zachowanie się ich jest analogiczne do operatora przeciążonego,który mógłby wystąpić np. w przypadku pisania kodu w C#.

������� �%� zwraca różnicę pomiędzy 3�� i czasem utworzenia obiektu. Możesz przete-stować obie właściwości za pomocą kilku wierszy kodu:

(�&�@� ��B�=���'��������7�����������&����������������������'�"111��������@����'�����&�����������

W wierszu 1. tworzony jest egzemplarz klasy ����������������, zawierający predefi-niowane właściwości, o których dyskutowaliśmy. Konstruktor inicjuje pole � ����� �"%�. Druga instrukcja korzysta z metody �����, która usypia bieżący wątek. W naszymprzypadku jest to 1000 milisekund, czyli 1 sekunda. W wierszu 3. wywoływana jestmetoda właściwości ������� �%�, która zwraca obiekt �%�����. Na końcu wywoływa-na jest metoda ������# przy użyciu niejawnej referencji do obiektu �%�����.

Page 32: Visual Basic .NET. Księga eksperta

252 Część II � Zaawansowane programowanie zorientowane obiektowo

Te trzy proste wiersze kodu powodują w rezultacie wyświetlenie okna komunikatu po-kazanego na rysunku 7.3. Zgodnie z jego zawartością wygląda na to, że Visual Basic.NET potrzebował około 1,4 milisekundy na wywołanie funkcji 3�� od momentu obu-dzenia wątku.

���������Okno dialogowe

prezentujące

rozdzielczość

klasy TimeSpanw Visual Basic .NET

����� ��� ������������������ ��

Właściwości tylko do zapisu są wykorzystywane rzadziej niż wcześniej omawiane 9�"��)���, jednak istnieje kilka dobrych powodów, dla których ich sporadyczne wykorzy-stanie jest pomocne. Jedną z takich okazji jest właściwość związana z ustalaniem hasła.

Przypuśćmy, że mamy klasę sprawdzania tożsamości użytkownika, która akceptuje na-zwę użytkownika i zamaskowane hasło. O ile odpowiedź na zapytanie obiektu klienta„Kto jest użytkownikiem” byłaby wskazana, o tyle podobna odpowiedź na pytanie „Jakiejest jego hasło” byłaby już bardziej ryzykowna. W takim przypadku chcesz zapewne,aby użytkownik mógł wpisać hasło, ale jednocześnie żeby żaden z obiektów klienta niemógł tej informacji uzyskać. Właściwość ta mogłaby więc być zaimplementowana w spo-sób następujący:

��!��������=���� ��������

��� �8����@������'��������=������ ����������������2���2���� �����������������=����5�2������������������'����

Zauważ, że edytor kodu utworzył tylko blok ���, a wartość przypisywana do właściwo-ści jest przechowywana w odpowiadającym polu.

Z przyczyn praktycznych możesz zmodyfikować ten kod, aby był jeszcze bardziej bez-pieczny. Na przykład możesz zaimplementować właściwość =����)���, która będzie odrazu sprawdzać hasło w metodzie ��� tej właściwości, a potem wyczyści zmienną za-wierającą hasło. A informacją przechowywaną będzie jedynie to, czy podane hasło byłopoprawne. Taka zmiana zapobiegnie możliwości podglądnięcia obszaru pamięci odpo-wiadającej zawartości klasy przez programu szpiegujące.

Inne modyfikatory właściwości, jak �������, mogą być używane zarówno z właściwo-ściami, jak i z metodami. Aby uniknąć nadmiarowości informacji w Twoim kodzie,przyjmij, że modyfikatory mogą być stosowane w dowolnych składnikach klas, chybaże tekst wskazuje na coś innego. =����)��� i 9���)��� można stosować wyłącznie wewłaściwościach.

Page 33: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 253

� ���������������������������������!

Obszerna i wyczerpująca dyskusja na temat składowych ������ została zawarta w roz-dziale 11., „Składowe współdzielone”. Tam również znajdziesz przykłady ich stosowa-nia W tej chwili wystarczy powiedzieć, że właściwości mogą być współdzielone (������)lub występować jako składowe egzemplarzy. Właściwości ������ oznaczają, że możeszje wywołać w klasie — właściwość taka jest definiowana z użyciem słowa ������. Skła-dowe ������ mogą być także wywołane przez egzemplarze, za to składowe egzemplarzymogą być wywołane jedynie za pomocą egzemplarza klasy. Oto przykład:

��� ��������/���@������'�����B�&���� ����������-������/��������'��������7�����������-��������'����

W przykładzie zdefiniowana jest właściwość ����, ������ i 9���)��� o nazwie 3�%�.Ponieważ nazwa klasy nigdy się nie zmienia, chyba że zmiany dokona programistaw kodzie programu, powyższa metoda może mieć charakter tylko do odczytu. Zrobieniemetody publiczną oznacza, że konsumenci mogą z tej metody korzystać, a użycie mo-dyfikatora ������ zwalnia nas z potrzeby posiadania obiektu (egzemplarza klasy) w celuzapytania klasy „Jak się nazywasz?” Jeśli klasa jest nazwana jako ����������������,możemy wywołać jej metodę &�� pisząc ����������������'3�%�.

Właściwość 3�%� w powyższym fragmencie pokazuje bardzo istotną różnicę między Vi-sual Basic .NET a VB6. Właściwość ta jest bardzo sprecyzowana w swoich zamierze-niach — Visual Basic .NET umożliwia nam określenie swoich zamiarów co do właści-wości i wprowadzenie ich w życie za pomocą bardzo precyzyjnej gramatyki języka.W VB6 mogliśmy zdefiniować właściwość tylko do odczytu poprzez instrukcję ?���������, lecz jej status tylko-do-odczytu był ukryty. Poza tym, nie mogliśmy definio-wać składowych ������.

Oczywiście można dyskutować, czy tak niewielkie zmiany semantyczne w języku rze-czywiście są istotne. Odpowiedź brzmi: „Są jak najbardziej istotne”. Programowaniejest niemal tak samo precyzyjne jak matematyka, a języki, w których programujemy,powinny być ekspresyjne w sposób umożliwiający uniknięcie tworzenia niejednoznacz-nego, głupiego i nadmiarowego kodu. Niuanse i subtelność w wyrażaniu się powinnybyć pozostawione kochankom i mężom stanu.

������������#���������������

Atrybuty nie są całkowicie nowym zagadnieniem w Visual Basic .NET. Mogłeś się z nimispotkać już w VB6. Na przykład otwórz w edytorze tekstu moduł klasy VB6 — plik.CLS — i zmień wartość atrybutu (���������+>����������!$�0������ na (��������+>����������!$�0� ��, a w rezultacie otrzymasz klasę utworzoną automatycznie. Jeśliklasa ma nazwę ����-, a jej metoda ���, to po powyższej modyfikacji napisanie ����-'��� powinno uruchomić kod klasy. Dzieje się tak dlatego, gdyż atrybut �+>����������!$jest mechanizmem, który sprawia, że formularze tworzą się automatycznie.

Page 34: Visual Basic .NET. Księga eksperta

254 Część II � Zaawansowane programowanie zorientowane obiektowo

No dobrze, dlaczego więc ten temat jest poruszany w książce o Visual Basic .NET?Atrybuty są istotne, gdyż stanowią pełnoprawny aspekt tworzenia aplikacji w VB .NET.Zostały również znacząco zmodyfikowane i ulepszone w stosunku do atrybutów zna-nych z VB6. Wykorzystaj właściwość 3�%� z poprzedniego podrozdziału do sprawdze-nia działania jednego z atrybutów:

��� ��������/���@������'�����B�&���� ������������3���������� ��������������������4�-��������/��������'��������7�������������-����������'����

Zwróć uwagę na wykorzystanie atrybutu w metodzie &��. (Atrybut $��##��������, nale-żący do klasy atrybutów z przestrzeni nazw �����%'$��#�������, był omawiany w roz-dziale 1., „Ujednolicone środowisko pracy Visual Studio”). Zapobiega on wchodzeniuprzez debuger do wnętrza tej metody.

Atrybuty mogą mieć zastosowanie w bardzo wielu miejscach w Visual Basic .NET. Naprzykład korzystasz ze znacznika atrybutu przy konwersji metody do metody =��. Byćmoże atrybuty zakończą swój żywot tak, jak szybkie samochody kończą go w rękachnastoletnich kierowców, jednak są one całkowicie odmienione w Visual Basic .NETi ich omówienie wymaga osobnego rozdziału. W tej chwili musisz jedynie wiedzieć, żejeśli znajdziesz znacznik @��%�A w kodzie VB .NET, to jest to atrybut. W rozdziale 12.,„Definiowanie atrybutów”, znajdziesz szczegółowe omówienie atrybutów.

�������������������

Metody są to funkcje i procedury, które należą do klasy lub struktury. Ponieważ strukturyzostały szczegółowo omówione w rozdziale 5., „Procedury, funkcje i struktury”, wszyst-kie nasze kolejne przykłady będą się opierać na klasach.

Cokolwiek jest możliwe do zrobienia z procedurą w module, to samo możesz uczynićz procedurą w klasie. Jedyną zasadą w przypadku metod jest kierowanie się z wyczu-ciem własnymi upodobaniami w trakcie pisania kodu. Osobiście lubię muzykę Beet-hovena i kapelę rockową Creed, więc prawdopodobnie moje upodobania różnią się odTwoich. Czy kwestia indywidualnych upodobań w przypadku programowania jest rze-czą istotną? I tak, i nie.

Jeśli jesteś programistą, możesz robić i tworzyć, co tylko Ci przyjdzie do głowy. Jeśliw dodatku nie dostajesz pieniędzy za kod, który piszesz, możesz puścić wodze fantazjii czynić prawdziwe cuda w swoich aplikacjach. Jednakże istnieje kilkanaście dobrychpozycji książkowych omawiających zasady dotyczące dobrego stylu w programowaniu.Jedną z ostatnio wydanych książek na ten temat jest pozycja Martina Fowlera traktującao refaktoringu. Świetne książki o programowaniu obiektowym napisali także Grady Bo-och, James Coplien i Bjarne Stroustrup. Do niektórych z tych pozycji znajdziesz odno-śniki w literaturze do tej książki.

Większość z przykładów prezentowanych w tej książce jest napisana z zastosowaniemw pewnym stopniu zasad refaktoringu. Ważniejszą rzeczą jest jednak to, że programuję

Page 35: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 255

w ten sposób od ponad 12 lat. Swoje aplikacje piszę takim stylem z bardzo prostego po-wodu: po ponad 10 latach programowania w sześciu językach i napisania milionów wier-szy kodu mój osobisty styl pozwala na tworzenie kodu o bardzo niewielkich rozmiarach,który może być wielokrotnie wykorzystywany, a przy tym jest łatwy do utrzymania i jestszybki. W tym miejscu chciałbym zaproponować kilka wskazówek, z których korzystampodczas implementowania metod.

� Staraj się tworzyć niewielki interfejs publiczny. Parafrazując Boocha (1995),implementuj garść metod i właściwości publicznych.

� Staraj się trafnie nazywać metody, unikając niestandardowych skrótów. W nazwiemetody stosuj czasownik, rzeczownik pozostawiając opisowi właściwości.

� Niech Twoje metody wykonują działanie ściśle odpowiadające ich nazwie;przyjmij zasadę: jedna metoda, jedno działanie. Nie twórz metod, którewykonują na raz zbyt wiele czynności.

� Ograniczaj metody do około pięciu wierszy kodu, a na pewno nigdy ponad to,co możesz za jednym razem zobaczyć na ekranie.

� Korzystaj z techniki refaktoringu „Wydzielanie metod”, dając nowym metodomtrafne nazwy zamiast pisania długich komentarzy.

� Rozważ zaimplementowanie wszystkich niepublicznych metod jako chronionychi wirtualnych — nigdy nie wiesz, kto będzie chciał do nich w przyszłości zaglądać.

Zasady te nie powstały w ciągu jednego dnia. Są one efektem naśladowania mistrzówprogramowania przez dłuższy czas. Stosowanie niektórych z nich — jak na przykładtworzenia krótkich, pojedynczych metod — zawsze wydawało się logiczne. Na koniecopowiem krótką historyjkę, ilustrującą sens stosowania się do wskazówek.

Swój pierwszy samochód kupiłem za 325 dolarów w wieku 15 lat. Było to w dniu,w którym uzyskałem na to pozwolenie mojego nauczyciela. Samochód ten możnabyło nazwać „toczącym się wrakiem”. Nic w tym samochodzie nie było pięknegopoza faktem, że potrafił jechać do przodu. Każde z kół miało inny rozmiar, dziuraw chłodnicy była wielkości piłki do footballu, skrzynia biegów nie do końca chciaładziałać poprawnie, a regulacja położenia siedzenia kierowcy nie miała sprawnejblokady. Gdy samochód się zatrzymywał, siedzenie jechało do przodu; gdy ruszałem,siedzenie ślizgało się do tyłu.

Krótko po kupieniu auta podjąłem decyzję o rozpoczęciu prac renowacyjnych. Remontrozpocząłem od naprawy paska napędzającego wentylator chłodnicy. Od ojca pożyczyłemnarzędzia i zacząłem naprawę od usunięcia wentylatora, a następnie pompy wodnej.Prawdopodobnie wyjąłbym też blok silnika, gdybym tylko wiedział, jak to zrobić— wszystko po to, aby wymienić pasek. Po kilku godzinach walki poddałem się.Śrubki, które znalazłem, wkręciłem z powrotem do silnika i zaprowadziłem samochóddo zakładu. Mechanik poluzował alternator, luzując tym samym naciąg starego paska,zdjął ten pasek, założył nowy, po czym naciągnął go odpowiednio dokręcając śrubyalternatora. Za 5 minut pracy skasował 35 dolców. Całkiem nieźle, jak na 5 minut.Zarobił 35 dolarów, jednak nie za to, że jego praca była ciężka, ale za to, że wiedział,jak ją zrobić. (No dobra, część tej historyjki zapożyczyłem ze starej bajki).

Morał z tej historii jest taki, że dokładna wiedza na temat, jak i dlaczego należy cośzrobić, jest jedynym usprawiedliwieniem na odchodzenie od ogólnie przyjętych zasad.Kod jest rzeczą tak osobistą, jak każda inna działalność twórcza. Przestrzeganiew przypadkach ogólnych dobrych zasad zwiększy Twoją produktywność;nieprzestrzeganie ich — udoskonali Twój talent.

Page 36: Visual Basic .NET. Księga eksperta

256 Część II � Zaawansowane programowanie zorientowane obiektowo

$��������������������������������������

Istnieją dwie specjalne metody, które będziesz musiał implementować. Określa się jemianem konstruktora i destruktora. Konstruktor jest wywoływany do inicjowania klasy,destruktor — do deinicjowania lub finalizacji klasy. W Visual Basic .NET konstruktorimplementowany jest jako ���3��, a destruktor występuje jako chroniona metoda ����������.

Każda klasa otrzymuje przynajmniej jednego konstruktora, odziedziczonego z klasy ba-zowej )�:���. )�:��� definiuje procedurę bez parametrów ���3��, która jest wywoły-wana, gdy piszesz kod jak poniżej:

(�&���������� ��� ��B�=�����������

�������������� jest dowolną poprawną nazwą zmiennej, a ������� � reprezentujejakikolwiek poprawny typ referencyjny. Z powyższej instrukcji można wywnioskować,że 3�� wygląda jak operator, jednak po prześledzeniu kilku kolejnych przykładów zoba-czysz, że taka instrukcja prowadzi bezpośrednio do metody ���3��,.. Metoda New —czyli konstruktor — jest wywoływana, gdy tworzysz nowe egzemplarze klas.

Gdy obiekt jest usuwany z pamięci, systemowy odzyskiwacz pamięci (garbage collector)wywołuje metodę �����������, czyli destruktora. Możesz zaimplementować destruktoraw celu deinicjalizacji obiektów poprzez dodanie metody �������� do swoich klas:

���� ����@!�����������������>���������

Mechanizm odzyskiwania pamięci często występuje jako skrót GC. GC jest równieżprzestrzenią nazw zawierającą systemowy odzyskiwacz pamięci.

Tradycyjnie, celem destruktora jest zwolnienie pamięci przypisanej obiektom zawartymw klasie. Ponieważ Visual Basic .NET zatrudnia GC, nie możesz być pewien, kiedy do-kładnie GC wywoła Twojego destruktora. Ciągle możesz korzystać z destruktora, abyusunąć obiekty ze swojej klasy, jeśli jednak posiadasz zasoby wrażliwe na czas, któremuszą być zwolnione natychmiast, dodaj publiczną metodę $������. W kolejnych przy-kładach będziemy korzystali z ��������$������,. w celu wykonania porządków ty-pu zamykanie plików czy zestawów rekordów.

!� ���� ���� ������"�

Agregacja jest pojęciem określającym dodawanie składowych do klas. Gdy dana klasaposiada składowe, które również są klasami, przy czym bierze ona jednocześnie odpo-wiedzialność za tworzenie i niszczenie egzemplarzy tych składowych, to o takim po-wiązaniu mówimy, że jest to agregacja. Natomiast gdy klasa posiada składowe będąceklasami, ale ich tworzeniem i usuwaniem zajmuje się jakaś jednostka z zewnątrz, tomówimy wówczas o związku. Gdy definiujesz agregacje w swojej klasie, musisz utwo-rzyć dla niej konstruktora.

Powód tworzenia konstruktora może być dowolny, jednak jeśli będziesz chciał two-rzyć egzemplarze składowych agregacyjnych, to konstruktor jest niezbędny. Domyślny

Page 37: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 257

konstruktor jest reprezentowany przez ���3�� i nie posiada parametrów. W celu jegozaprezentowania zdefiniowałem klasę ?����� ����, która wykorzystuje klasę �����%'!)' �*�9����� do załadowania pliku tekstowego do (����?���.

��� ����B�=�����������B�=����� ����9����5�B�=� ����9�����������

Kod będzie poprawny również wówczas, gdy usuniemy instrukcję ��+���'3��,..Semantycznie, wszystkie klasy pochodne muszą wywoływać konstruktoramacierzystego, jednak wygląda na to, że Visual Basic .NET w większościprzypadków robi to za Ciebie. Zamiast zgadywania, kiedy i dlaczego VB .NETwywołuje konstruktora klasy bazowej, zawsze umieszczaj ��+���'3��,. jakopierwszą instrukcję w swoim konstruktorze. Jeśli zechcesz wywołać konstruktoraparametrycznego w klasie potomnej, zamień po prostu wywołanie zwykłegokonstruktora na wywołanie konstruktora parametrycznego.

Nie posiadające parametrów ���3��,. wywołuje konstruktora klasy bazowej za po-mocą instrukcji ��+���'3��,.. ��+��� jest słowem zarezerwowanym, które umożliwiaodwoływanie się do składowych w klasie bazowej danej klasy, zwanej także klasąmacierzystą. Pamięcią wewnętrzną dla ?����� ���� jest (����?���. Ponieważ ?��"��� ���� — którego konstruktor jest pokazany — jest w posiadaniu (����?���, z tegowzględu konstruktor tworzy egzemplarz (����?���, zanim cokolwiek innego zostaniewykonane.

!� ���� �������#$� ������ ������"����������� ���

Jeśli w celu poprawnej inicjalizacji musisz przekazać do swojej klasy dane z zewnątrz,możesz zdefiniować konstruktora parametrycznego.

?����� ���� służy do załadowana pliku tekstowego do (����?���. Wydaje się oczywi-ste, że należałoby zainicjować obiekty ?����� ���� nazwą ładowanego pliku. Mającdwa konstruktory, możemy tworzyć egzemplarze bez znajomości nazwy pliku oraz gdytę nazwę znamy:

��� ����B�=���2��� ����B�&�� ��������������B�=��������B�&��5� ����B�&�������

Aby uniknąć powielania kodu, wydelegujemy część odpowiedzialną za konstrukcję kla-sy do bezparametrycznego konstruktora z ��'3��,. i przechowamy parametr w pamięcipodręcznej.

Posiadanie w tej samej klasie dwóch metod ��� 3�� oznacza, że konstruktor zostałprzeciążony. Konstruktory nie zezwalają na użycie słowa kluczowego )��������. Jest tospecjalna zasada wprowadzona dla konstruktorów przez inżynierów Visual Basic .NET.(Więcej na temat metod przeciążonych znajdziesz w podrozdziale „Korzystanie z mo-dyfikatorów”).

Page 38: Visual Basic .NET. Księga eksperta

258 Część II � Zaawansowane programowanie zorientowane obiektowo

����� ��� ���������"�

Jeśli przypisujesz pamięć w momencie wywołania konstruktora, musisz również zwolnićją, implementując do tego celu destruktora. ���3�� jest używany podobnie jak ����>!��������� w VB6, a ����������� w sposób analogiczny do ����> ��%�����. Obiektyutworzone przez konstruktora muszą być usunięte za pomocą destruktora.

Generalnie, jeśli w Twojej klasie nie ma zdefiniowanego konstruktora, prawdopodobnierównież nie potrzebujesz destruktora. Oto podstawowa forma, w jakiej występuje de-struktor ��������, zaimplementowana w przykładowej klasie ?����� ����:

���� ����@!�����������������>�����(��'�����������

Implementując destruktora na podstawie metody $������, możesz bezpośrednio zwal-niać obiekty za pomocą tej metody, jeszcze zanim uczyni to GC. Istnieją określone za-sady i reguły dotyczące zwalniania zasobów — więcej informacji na ten temat znaj-dziesz w następnym podrozdziale.

Destruktor �������� jest chroniony (��������); z tego względu, nie możesz go bezpo-średnio wywołać — jest on wywoływany przez GC. Oto podstawowe zasady obowią-zujące przy implementacji destruktora:

� Metody �������� powodują obciążenie systemu. Nie definiuj przeciążonejmetody ��������, jeśli nie jest to konieczne.

� Nie definiuj metody �������� jako publicznej.

� Zwalniaj posiadane obiekty za pomocą metody $������; korzystaj z ��������wywołując $������.

� Nie likwiduj referencji w swoim destruktorze; jeśli Twój kod nie utworzyłobiektu, jest to referencja, a nie agregacja.

� Nie twórz obiektów ani nie korzystaj z innych obiektów w metodzie ��������;destruktory służą wyłącznie do czyszczenia pamięci i zwalniania zasobów.

� W metodzie �������� jako pierwszą instrukcję zawsze stosuj ��+���'��������.

Ze względu na to, że nie wiemy, kiedy GC zwalnia obiekty, można zaimplementowaćmetodę ����� $������ i wywoływać ją jawnie w bloku ochrony zasobów �������;dzięki temu uzyskamy konkretną finalizację obiektów takich jak np. strumienie danychczy wątki.

����� ��� ������� �����

Destruktory są chronione. Konsumenci nie mogą i nie powinni mieć możliwości bezpo-średniego wywoływania metody ��������. Możesz jawnie uruchomić systemowy odzy-skiwacz pamięci za pomocą instrukcji �����%'& ' ������, lecz nie jest to zalecanapraktyka i powoduje znaczne obciążenie systemu.

Page 39: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 259

Jeśli chcesz wyczyścić znaczące obiekty, zastosuj metodę �����$������ i ją wywołaj.Oto kilka pożytecznych wskazówek dotyczących implementacji metody $������:

� Dodawaj metodę $������, wykorzystując interfejs !$���������. (!$���������posiada jedną metodę, $������, a w systemie pomocy Visual Studio .NETznajdziesz przykłady klas z zaimplementowanym tym interfejsem).

� Jeśli posiadasz istotne zasoby, takie jak uchwyty Windows, zestawy rekordówlub strumienie plików, które muszą być zwolnione do systemu zaraz pozakończeniu korzystania z nich, wówczas utwórz publiczną metodę $������.

� Zaprojektuj mechanizm powstrzymujący usuwanie, jeśli użytkownikbezpośrednio wywoła metodę $������.

� Jeśli klasa bazowa implementuje !$���������, wywołaj metodę $������ z klasybazowej.

� Zaimplementuj metodę ��������, która wywoła $������. W ten sposóbupewnisz się, że $������ będzie zawsze wywoływana.

� Zwalniaj posiadane obiekty w metodzie $������.

� Rozważ możliwość wygenerowania wyjątku )�:���$��������*�������,w przypadku gdy konsument próbuje skorzystać z obiektu po wcześniejszymwywołaniu metody $������.

� W swojej metodzie $������ wywołaj & '���������������,��. aby powiedziećGC, że nie musi uruchamiać metody ��������.

� Zezwól na wywoływanie obiektu $������ więcej niż jeden raz. Drugie i kolejnewywołania nie powinny wykonywać żadnych operacji.

Przy wykorzystaniu tych wskazówek poniżej została utworzona metoda $������ dla?����� ����:

��� ����(��'������6&'��&�����6(��'�������(��'���������� ��(��'����� ����������5��������67���(��'���������������������(��'�����5���������������� ����9����5�B��������-���''����������>�����������

Metoda $������ implementuje !$���������'$������ (przez to wiemy, że !%���%����!$��������� jest zawarte w naszym ?����� ����). Lokalna zmienna statyczna jest wy-korzystana w celu umożliwienia bezpiecznego wywoływania $������ więcej niż jedenraz. Druga instrukcja ustawia odpowiednią wartość +������, wskazując, że $�������była już wywołana. Metoda ?����� ����' ���� jest wywoływana w celu zamknięcia �*�9�����, co nie zostało jeszcze pokazane, a (����?��� zostaje przypisany 3�����#.Na końcu, & '��������������� informuje GC, że nie ma potrzeby wywoływania me-tody �������� dla danego obiektu.

Page 40: Visual Basic .NET. Księga eksperta

260 Część II � Zaawansowane programowanie zorientowane obiektowo

%��&�� ��������������

Podczas dyskusji o klasach zauważyłeś pewnie częste korzystanie z dwóch specyficz-nych słów kluczowych — ��+��� oraz �� ����. ��+���, jak już widziałeś, zezwala nawywoływanie metod w klasie bazowej tworzonej klasy, które mogą być przeciążane;rozwiązuje to problem niejednoznaczności klas.

�� ���� jest przybliżonym odpowiednikiem referencji do samej siebie ��. �� ���� za-kłada, że jakiekolwiek metody wywołane z niej są zadeklarowane jako 3��)����������.�� ���� wywołuje metodę, nie biorąc pod uwagę typu obiektu, jaki posiada on w trakciedziałania aplikacji, efektywnie omijając polimorficzne zachowanie. Ze względu na to,że �� ���� jest referencją do obiektu, nie możesz z niej korzystać w metodach ������.

Referencja do siebie �� została przeniesiona do Visual Basic .NET. �� do działania wy-maga egzemplarza. �� ���� wywołuje metodę w tej samej klasie, natomiast �� wywołujemetodę w obiekcie przypisanym przez ��, to znaczy, w sposób polimorficzny. Przyjrzyjsię następującym klasom.

��� ������������"����� �@!��������������� ��������������� ����B�=����������� �������������������

��� ������������$��6�������������"����� �@!������������� �������������������

Gdy tworzony jest obiekt typu ����B, konstruktor w ����- wywołuje ����B'���. Jeśli��'��� zamienimy na �� ����'���, wówczas wywołana będzie ����-'���.

�������� ����������������������

Metody są to funkcje i procedury, które zdefiniowane zostały w ramach klasy lub struk-tury. Jedynym wyzwaniem, które pojawia się podczas implementacji metod, jest opra-cowanie odpowiednich algorytmów rozwiązujących dany problem, napisanie dla nichjak najprostszego kodu oraz określenie dostępu do tworzonych metod wraz z użyciemodpowiednich modyfikatorów, które byłyby dla nich najbardziej odpowiednie.

Niestety, sposób definiowania metod jest zagadnieniem bardzo subiektywnym. Najlep-szym sposobem na nauczenie się implementowania metod jest analizowanie i pisaniejak największej ilości kodu, a następnie wybranie stylu naszym zdaniem najlepszego.Nie bój się eksperymentować i zmieniać kod już napisany. Wydruk 7.6 przedstawiakompletną klasę ?����� ����.

Page 41: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 261

�� ������Zawartość klasy LoaderClass

�"#�6&'����������&�6@�$#�%#���� �������9�����������)#���6&'��&�����6(��'�������*#�+#�����!���������B�&�� ���������,#�����!�����/������ ������/������.#�����!����� ����9���� �� ����9����0#������ ��!����@��������2�������� ���������"1#""#�����!�������(��������2�������� ���������"$#�����/�����!����@�����������"%#���������")#"*#������ ���'���������B�&���� ��������"+#�����-��",#�������/����������B�&�".#���������-��"0#�����������2���2���� ���������$1#������������B�&��5�2���$"#������������$$#���������'����$%#$)#������ �@!�����������@'����$*#�����67���/������6��B������������$+#��������/������5������@'������������B�&��$,#���������$.#�����������=�B�=� ''�� ������� �'������7����������������'����$0#���������67%1#���������%"#%$#������ �@!�����������@'�����2��� ����B�&�� ���������%%#���������B�&��5� ����B�&�%)#�����@'����%*#���������%+#%,#������ �����������%.#�����67���/������6��B��������������������%0#������/�������������)1#������/������5�B������)"#���������)$#)%#�����!������ ����� �����2�������� ���������� ���������))#�����67�������5����������/����������)*#�����(�����������)*#������ ����9���� ��������),#�����/��������).#��������� ����)0#*1#�����!������ �����/��������� ���������*"#�����/�����B����(��'����� �� ���� ����/������/���9������*$#��������� ����*%#*)#������ ����9�����**#�����8������/���������*+#������� ''�� ������(��!������*,#���������8����

Page 42: Visual Basic .NET. Księga eksperta

262 Część II � Zaawansowane programowanie zorientowane obiektowo

*.#���������*0#+1#������ ����B�=��+"#������������B�=��+$#������ ����9����5�B�=� ����9�����+%#���������+)#+*#������ ����B�=���2��� ����B�&�� ���������++#��������B�=��+,#���������B�&��5� ����B�&�+.#���������+0#,1#�����!�����(��'����� ����������5������,"#,$#������ ����(��'������6&'��&�����6(��'�������(��'���,%#�����67���(��'������������������,)#������(��'�����5����,*#������������,+#������ ����9����5�B������,,#���������,.#,0#������� ����@!�����������������>���.1#�����(��'�����."#������������������>���.$#���������.%#.)#������ ���������� �����9������2��� ����B�&��A.*#����� ���������� ��9����������.+#.,#�����(�&� 9������ ��B�=�9����������� ����B�&��..#����� 9������@'����.0#����� 9������9�����01#�����/����� 9�����0"#0$#��������� ����0%#����������

Klasa ?����� ���� definiuje metodę $� �*�, dwie metody )��� oraz ����, (��, 9�����#i ?���. $� �*� jest metodą prywatną; jej zadanie polega na wygenerowaniu zdarzeniaw celu poinformowania o jakichkolwiek obiektach, które mogą chcieć podsłuchać pro-ces ładowania. Obie metody )��� są publiczne; zostały zdefiniowane z modyfikatorami)��������, aby umożliwić konsumentom otwieranie pliku z przekazaniem jego nazwyw argumencie metody lub bez tego argumentu, zakładając w takim przypadku, że nazwapliku została wcześniej przypisana w wywołaniu konstruktora lub poprzez modyfikacjęwartości właściwości. (Właściwość ����3�%� jest zdefiniowana w wierszach 15. – 22.).Metoda (�� eliminuje potrzebę istnienia zmiennej tymczasowej. Możemy przekazaćwynik metody �*�9�����'9���?��� jako parametr do (��, która zwróci nam +������wskazujący, czy chcemy wartość czy nie. Funkcja 9�����# zwraca wartość +������określającą, że dodaliśmy tekst i że nie wywołaliśmy metody $������ (wiersze 50. –52.). Przy okazji w wierszu 51. widzimy przykład zastosowania operatora działaniaskróconego (��(���. Jeśli metoda $������ została wywołana, 3��� $������� zostajeskrócona; w przeciwnym razie zostaje odczytywany następny wiersz tekstu. Jeśli �9�"����'9���?��� dojdzie do końca pliku, metoda 9���?��� zwróci pusty ciąg (11), a 9�"����# zwróci �����. Ponieważ rozdzieliliśmy działanie 9�����# i (��, metoda ?��� jestbardzo prosta i składa się jedynie z pętli =���� (wiersze 54. – 58.).

Page 43: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 263

Jedynymi metodami publicznymi w naszej klasie są )���, ���� i 9���. Z tego względuklasa jest bardzo łatwa do obsługi przez konsumentów. Pozostałe metody wspomagajądziałanie metod publicznych i nie muszą być prezentowane użytkownikom, a tym bar-dziej przez nich wywoływane. Są one więc prywatne.

Porównaj pojedynczego muzyka z orkiestrą. Jeśli masz jednego muzyka, który grana jednym instrumencie, rodzaj muzyki przez niego prezentowany jest siłą rzeczyograniczony. Jeśli natomiast posiadasz całą orkiestrę z kilkudziesięcioosobowymskładem, ich możliwości i różnorodność muzyki przez nich granej sąnieporównywalnie większe.

Monolityczne metody są jak samotny muzyk; przyjemne, lecz niezbyt różnorodne.Wiele pojedynczych metod — myśląc o konstruktorach przeciążonych w roli sekcjidętej — oznacza, że każda metoda może się w czymś specjalizować i byćwykorzystywana bardziej różnorodnie.

W naszym konkretnym przykładzie prawdopodobnie nie wykorzystamy ponownie metod(��, 9�����# czy $� �*�. To, co uzyskujesz dzięki pojedynczym funkcjom, to łatwość ichimplementacji oraz małe prawdopodobieństwo, że z ich powodu wystąpią jakieś błędy.Kolejną zaletą, może nie już tak oczywistą, jest to, że takie metody mogą być przecią-żane w podklasach. (Jeśli chciałbyś rozszerzyć na podklasę prywatne metody ?�����" ����, musiałbyś zmienić je na chronione, co z drugiej strony jest czynnością trywialną).Jeśli natomiast będziesz korzystał z mniejszej liczby monolitycznych metod, będzieszmiał mniej możliwości do ich przeciążania czy rozszerzania działalności.

"�������������� �������������

Modyfikatory metod pozwalają nam na uzyskanie większej kontroli nad ich implemen-tacjami.

�����#$� �����

Modyfikator )�������� jest wykorzystywany do wskazania, że w danej klasie dwie lubwięcej metod jest przeciążonych. Przykładem przeciążonej metody jest ?����� ����')���.

Dzięki przeciążaniu możliwa jest implementacja metod, które wykonują semantycznietę samą operację, ale różnią się liczbą lub typem argumentów. Weźmy dla przykładumetodę, która wypisuje tekst na konsolę, ����. Bez przeciążania musielibyśmy wpro-wadzić unikalne nazwy dla metod wypisujących poszczególne typy, na przykład ����"!���#��, ���������#, ����$���. Takie podejście wymagałoby od użytkowników na-uczenia się nazw wielu metod, które wykonują to samo zadanie. Dzięki przeciążaniuwszystkie powyższe metody mogą nazywać się ����, a kompilator, na podstawie typuargumentu, sam wywoływałby odpowiednią metodę; pozostawmy więc wykonywanienudnych zadań kompilatorowi, a sami zajmijmy się bardziej istotniejszymi sprawami.

Nagłówek procedury, liczba i typ argumentów oraz typ zwracany (jeśli procedura jestfunkcją) tworzą wspólnie sygnaturę procedury.

Również właściwości mogą być przeciążane.

Page 44: Visual Basic .NET. Księga eksperta

264 Część II � Zaawansowane programowanie zorientowane obiektowo

Oto podstawowe wskazówki dotyczące używania modyfikatora )��������:

� Jeśli w Twoim kodzie występują metody przeciążone, użycie słowa )��������jest niezbędne (na wydruku 7.6 możesz sprawdzić, w którym miejscu należy jestosować).

� Metody przeciążone muszą posiadać różną liczbę lub typ parametrów (VisualBasic .NET umożliwia przeciążanie metod z bardzo podobnymi typami, jak np.?��# i !���#��).

� Nie można przeciążać metod, zmieniając jedynie modyfikator dostępu, np. ������.

� Nie można przeciążać metod, zmieniając tylko rodzaj przekazywanychargumentów (+���� i +�9��)

� Nie możesz przeciążać metod, zmieniając wyłącznie nazwy parametrów,a pozostawiając takie same typy.

� Nie możesz przeciążać metod, modyfikując jedynie typ zwracany przez metodę,jednak oczywiście mogą istnieć dwie metody przeciążone różniące się typemzwracanej wartości. Na przykład, nie mogą być przeciążone procedura i funkcjao takich samych nazwach i argumentach, nie jest to również możliwew przypadku dwóch funkcji z takimi samymi argumentami, które różnią sięjedynie typem zwracanej wartości.

Jeśli znajdziesz się w sytuacji, gdy wykonywana operacja jest taka sama, a różni się typdanych, wówczas potrzebujesz metody przeciążonej. Gdy natomiast implementujeszdwie metody o takim samym kodzie, które różnią się jedynie wartością jednego lub kil-ku parametrów, zastosuj pojedynczą metodę z parametrem )�������.

������ �� �����

Modyfikator )�������� umożliwia polimorfizm. Używasz go, gdy chcesz rozszerzyćlub zmodyfikować zachowanie się metody w klasie bazowej. Metoda klasy bazowej musimieć taką samą sygnaturę jak metoda ją przesłaniająca.

Do modyfikatora )�������� powrócimy w rozdziale 10., „Dziedziczenie i polimorfizm”.

'���!����������������(�'�����������)����������

Modyfikatory )����������, ���)������� i 3��)���������� są używane do obsługi me-tod, które mogą być przesłaniane i które muszą być przesłaniane.

)���������� i 3��)���������� wzajemnie się wykluczają. Pierwszy z modyfikatorów,)����������, wskazuje, że metoda może być przesłonięta. 3��)���������� przy nazwiemetody oznacza, że nie możesz jej przesłaniać. ���)������� wskazuje, że metoda jestabstrakcyjna, a klasy potomne muszą implementować tego typu metody w klasie macie-rzystej. Z ���)������� wynika jednoznacznie, że metoda jest przesłanialna, nie mawięc potrzeby stosowania w niej modyfikatora )����������, a obecność 3��)����������w metodzie ���)������� nie ma żadnego sensu.

Page 45: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 265

Metody ���)������� nie posiadają implementacji w klasie, w której zostały z takimmodyfikatorem zadeklarowane. Metody te są odpowiednikiem czysto wirtualnych me-tod w C++ i wirtualnych metod abstrakcyjnych w Object Pascal; potomkowie muszą ta-kie metody implementować.

������� ��������!�������%������

Jeśli chcesz, aby klasa potomna mogła korzystać z nazwy poprzednio wprowadzonejw klasie nadrzędnej, skorzystaj ze słowa �������. Nazwy zakryte nie są usuwane z kla-sy macierzystej; słowo ������� zezwala po prostu na powtórne wprowadzenie w klasiepotomnej poprzednio użytej nazwy bez wystąpienia błędu kompilacji.

Składowe w klasie potomnej nie muszą być tego samego typu jak składowe zakryte;dwie składowe muszą mieć jedynie identyczne nazwy. Jakakolwiek składowa w klasiepotomnej może zakryć dowolną składową klasy nadrzędnej. Metoda w klasie potomnejmoże zakryć pole, właściwość, metodę lub zdarzenie klasy nadrzędnej. Poniższy frag-ment demonstruje wykorzystanie modyfikatora ������� do ponownego wprowadzeniametody w klasie potomnej z taką samą nazwą jak metoda w klasie nadrzędnej.

��� ������� ����� ��������������������������

��� ����������6�������� ����� ������=���������������������������

Wydruk pokazuje dwie klasy, A i B. B jest podklasą A; to znaczy, A jest klasą nadrzęd-ną (rodzicem) klasy B. Obie klasy posiadają metodę ���. Skorzystanie ze słowa �������w +'��� oznacza, że +'��� zakrywa ('���. Jeśli posiadasz dwie identyczne nazwyw dwóch klasach związanych ze sobą dziedzicznością, musisz skorzystać albo z mody-fikatora �������, albo z )��������. (W rozdziale 10., „Dziedziczenie i polimorfizm”,znajdziesz szczegółowe informacje na temat używania ������� i )��������).

'���!������%����

Składowe ������ są dostępne bez potrzeby tworzenia egzemplarzy typów referencyj-nych lub bezpośrednich — odpowiednio klas lub struktur. W rozdziale 11., „Składowewspółdzielone”, znajdziesz dokładne omówienie składowych współdzielonych.

"��������������� ��������������

Klasy wspierają bardzo mądre powiedzenie divide et impera, dziel i rządź. Jako kon-struktor klasy, możesz skupić się podczas definiowania wyłącznie na sposobie jej im-plementacji. Gdy korzystasz z klasy, stajesz się jej konsumentem. W tym momencieinteresują Cię jedynie składowe publiczne, a w przypadku klas potomnych — składowepubliczne i chronione.

Page 46: Visual Basic .NET. Księga eksperta

266 Część II � Zaawansowane programowanie zorientowane obiektowo

Zaletą modyfikatorów dostępu jest to, że jako konsument nigdy nie musisz martwić sięo składowe prywatne i zazwyczaj nie musisz również myśleć o składowych chronio-nych. Jeśli będziesz pamiętał o ogólnej zasadzie mówiącej o definiowaniu nie więcejniż sześciu składowych publicznych w pojedynczej klasie, jako konsument takiej klasybędziesz zwolniony z ciężaru większości detali implementacyjnych, które ukryte zosta-ną w składowych prywatnych i chronionych. Poprzez pewne zarządzanie kodem i sto-sowanie specyfikatorów dostępu ograniczających liczbę składowych, z jakimi muszą sięuporać konsumenci, upraszczasz swój kod, przez co staje się on łatwiejszy do zarządza-nia i utrzymania.

W metodach możesz korzystać ze specyfikatorów dostępu ����, ��������, ������i ��������� ������. Na początku tego rozdziału, w podrozdziale „Używanie specyfi-katorów dostępu do klas”, zostały omówione poszczególne specyfikatory. Poniższa listabardzo krótko omawia ich wpływ na metody:

� Metody ���� mogą być wywołane wewnętrznie lub przez dowolnegokonsumenta.

� Metody �������� mogą być wywołane przez generalizatora (klasę potomną)lub wewnętrznie.

� Metody ������ mogą być wywoływane wyłącznie wewnętrznie.

� Metody ������ mogą być wywołane jedynie w obrębie tej samej aplikacji.

� Metody �������� ������ mogą być wywołane wewnętrznie lub przez potomkaw obrębie tej samej aplikacji.

W książce znajdziesz setki przykładów wykorzystujących specyfikatory dostępu, a kil-kanaście w tym rozdziale. W pierwszym podrozdziale, „Definiowanie klas”, znajdzieszogólne uwagi na temat liczby metod i stosowania specyfikatorów.

���������������������

Gdy chcesz poinformować konsumenta klasy, że coś się wewnątrz tej klasy wydarzyło,możesz to przedstawić za pomocą zdarzenia:

��� ��!����@��������2�������� ���������

��!�������(��������2�������� �����������/�����!����@�����������������

Klasa ?����� ���� (zobacz wydruk 7.6) wywołuje zdarzenie )� �*� dla każdego wierszaodczytywanego z pliku tekstu. Zaletą korzystania ze zdarzeń jest to, że klasa nie musiwiedzieć, którzy konsumenci są zainteresowani otrzymywaniem informacji o zajściuzdarzenia. Kod ?����� ���� nie zmienia się w zależności od tego, czy któryś z konsu-mentów obsługuje zdarzenie czy nie.

Instrukcja �����������)� �*�,+����� �*��(�������#. tworzy niejawnie typ $���#���.Konsument, który chce obsłużyć zdarzenie )� �*� wygenerowane przez ?����� ����,

Page 47: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 267

może do tego celu użyć instrukcji =��������� lub (���������. Oto przykład użycia dru-giej z nich:

�����������9������@�����<� ������@7�@�����

Obiekt zawierający metodę )� �*� (w powyższej instrukcji) jest dodawany do listy wy-wołań $���#��� delegacji �?�����')� �*�.

Zdarzenia nie są polimorficzne. Oznacza to, że nie możesz jawnie przeciążać metodw klasach potomnych. Ogólną strategią stosowaną w takim przypadku jest opakowanieinstrukcji 9���������� w metodę i użycie tej metody (zobacz $� �*�) jako proxy w celuwywołania zdarzenia. Poprzez skorzystanie z proxy przy wywoływaniu zdarzeń, mo-żemy przesłonić go w klasach potomnych, gdy tylko chcemy zmienić zachowanie sięzdarzenia w momencie jego wywołania.

Obsługa zdarzeń zmieniła się znacząco w Visual Basic .NET, włączając w to wprowa-dzenie klas $���#��� i ��������$���#���, które bardzo usprawniły tę obsługę. Roz-dział 8., „Dodawanie zdarzeń” oraz 9., „Delgacje” szczegółowo omawia tematy obsługizdarzeń i delegacji.

�����������������������������

Klasa zagnieżdżona jest po prostu klasą zdefiniowaną w klasie. Klasy zagnieżdżonemogą być definiowane ze wszystkich elementów dowolnej innej klasy. Oto szkielet kodudla klasy zagnieżdżonej:

��� �������@�������� �������B�������������������������

Celem tworzenia klas zagnieżdżonych jest zgromadzenie grupy elementów posiadają-cych wspólne cechy w obrębie zawierającej je klasy. Na przykład, jeśli masz klasę i ja-kieś pola, właściwości i metody definiujące pewną koncepcję, jednak są one osobno,możesz zaimplementować klasę zagnieżdżoną, w której zgromadzisz te elementy.

Generalnie, nie będziesz często wykorzystywał klas zagnieżdżonych. Jakakolwiek im-plementacja, która może być zrobiona z użyciem klas zagnieżdżonych, może być z po-wodzeniem zrobiona bez nich. Jeśli temat ten Cię bardziej interesuje, możesz poczytaćna temat bardziej zaawansowanych tworów, np. o idiomie list-koperta, w książce JamesaCopliena „Advanced C++”. Wydruk 7.7 przedstawia przykład klas zagnieżdżonych,prezentując sposoby ich implementacji i gramatykę języka.

�� �����Klasy zagnieżdżone, dziedziczenie i wielowątkowość w programie demonstracyjnym

TrafficLight.sln

��"#���� ���������������$#�H/���������FI���=��'��� >������%#������ ��!����@����������2���������� �������&�@�E� �<�A��)#�������2����� �������&��!��� ����

Page 48: Visual Basic .NET. Księga eksperta

268 Część II � Zaawansowane programowanie zorientowane obiektowo

��*#��+#������ ����(��=���2���-��'�� � ��-��'�� ����,#�����-��'�� �����/� �����������������=�<�/� ����.#�����(��=9������-��'�� ���0#����������"1#�""#������ ����B�=���2���/� �� ��/� ��������"$#������/� ��5�/� ��"%#������������9��������")#��������@�-�������"*#��������������������"+#����������",#�".#������ ����(��'������"0#���������� �(���� ����������5�������$1#�����67��(������������������$"#�����(����5�����$$#�����J������������$%#�����-���''����������>������$)#����������$*#�$+#������ ����B������������$,#�����8��������������6� ��!���$.#�������������������'�����'��&�����$0#���������������������%1#�������(����������%"#���������8�����%$#����������%%#�%)#�H����/������%*#�%+#�H/���������FI���=�� �����������%,#�%.#���G�(����F����%0#������� ����@!�����������������>����)1#�����(��'������)"#����������)$#�)%#������� ����������������������))#�������������5�B�=������������������ ������@7�B�����������)*#�������������6��� F������5�����)+#�������������������),#����������).#�)0#������� ���������������������*1#���������������������*"#����������*$#�*%#������� ����������'���������*)#������������� �������**#�������������;������*+#����������*,#�*.#������� �������J������������*0#��������'���������+1#�������������5�B�������+"#���������

Page 49: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 269

�+$#�+%#������� �������(��=9��������2���-��'�� � ��-��'�� ���+)#�����(�&�6� ��6�������+*#���������6�5�1�����9������-��C''�������1��++#��������9������6��(��=�-��'�� ��+,#�����B����+.#����������+0#�,1#�H����/������,"#�,$#�H/���������FI���=��'��=�������,%#�����!�����9�������� ��9�����5�A�,)#�����:B�=�-����9������<�B�=�K����=9������<�B�=�/��9������?�,*#�����!�����/� �� ��/� �������,+#�����!������������ �������������������,,#�,.#�����!����/���@������'�����-������� ��9�����,0#�����-���.1#�������/������9������1��."#���������-���.$#���������'�����.%#�.)#�����!����/���@������'�����K����=��� ��9�����.*#�����-���.+#�������/������9������"��.,#���������-���..#���������'�����.0#�01#�����!����/���@������'�����/����� ��9�����0"#�����-���0$#�������/������9������$��0%#���������-���0)#���������'�����0*#�0+#�����!����/���@������'�����/� ���� ��/� �������0,#�����-���0.#�������/������/� ��00#���������-��"11#���������'����"1"#"1$#�����!��������������9�������"1%#"1)#�����(�&�6� ��6������"1*#���������6�5�1�����9������-��C''�������1�"1+#��������9������6��/� ��5�-��/� ��6�"1,#�����B���"1.#"10#���������""1#"""#�����!����������@�-������""$#�����-�����������5����""%#���������"")#""*#�����!�������(���������""+#�����/�����!����@����������<�B�������"",#���������"".#

Page 50: Visual Basic .NET. Księga eksperta

270 Część II � Zaawansowane programowanie zorientowane obiektowo

""0#"$1#�����!������ �����-��/� ����2���6����� ��6�������� ��/� ������"$"#�����/�����B�=�/� �������/� ��9�7��L�"1<�A"$$#���������/� ����'�L�"1�L��6��������/�����$�M�6������N�%�O�/� ����������<�A"$%#���������/� ��8�����M�$1<��6��������/����/� ���������N�%���M�$1�"$)#��������� ����"$*#"$+#�����!��������������������"$,#���������� �������� ��6�������5�1"$.#������������5���������L�"������%"$0#�����(�&�6� ��6������"%1#"%"#���������6�5��9������-��9�=�������1�����A"%$#��������9������-��C''�������1�"%%#��������9������6��������5�6�5�������"%)#�����B���"%*#���������"%+#"%,#�����!������ ���������'��&���� ��6������"%.#���������� ����� ��6�������5�:"111<�*111?"%0#�����67��K����=������������")1#�������/�������1�")"#���������")$#�������/�������"�")%#���������67"))#��������� ����")*#")+#�H����/�����"),#").#")0#�H/���������FI���=��>�����P�P�����"*1#"*"#���G�2������ ����� ��B������9����������"*$#���G������ �����7�������������������������� ������"*%#"*)#�����!�������6�������������9����"**#�������� ������� ����������5������"*+#�������� �/� �� ��/� ������"*,#"*.#��������� �������@!�������/���@������'�����A"*0#����������� ������� ��������"+1#"+"#��������� ������ �����-��������� ������"+$#�������67�������������"+%#���������/��������� �����"�"+)#�����������"+*#���������/��������� �����1�"++#�����������67"+,#����������� ����"+.#"+0#�������� ����(��=���2���-��'�� � ��-��'�� ��",1#�������-��'�� ���������'���-��������<�/� ��","#�����������",$#",%#��������� ����@!�����������������>���",)#�������/� ��5�B������",*#�����������",+#������������

Page 51: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 271

",,#",.#���G�Q�����P�P����F�����/��9����<��>���>� >��>�9����",0#�����!����������/��9����".1#�����6��������9����"."#".$#��������� ����@!��������/���@������'��������� ������� ��������".%#�������-��".)#�������������� �������� �������5�:�������-���<�A".*#������������������/��?".+#���������/���������".,#�����������-��"..#�����������'����".0#������������"01#"0"#���G�Q�����P�P����F�����K����=9����<��>���>� >��>�9����"0$#�����!����������K����=9����"0%#�����6��������9����"0)#"0*#��������� ����@!��������/���@������'��������� ������� ��������"0+#�������-��"0,#�������������� �������� �������5�:�������-���<�A"0.#������������������K����=?"00#���������/���������$11#�����������-��$1"#�����������'����$1$#$1%#������������$1)#$1*#���G�Q�����P�P����F�����-����9����<��>���>� >��>�9����$1+#�����!����������-����9����$1,#�����6��������9����$1.#��������� ����@!��������/���@������'��������� ������� ��������$10#�������-��$"1#�������������� �������� �������5�:�������-���<�A$""#������������������-����?$"$#���������/���������$"%#�����������-��$")#�����������'����$"*#������������$"+#�H����/�����$",#$".#����������

Ze względu na to, że wydruk ten jest bardzo długi, jego szczegółowe omówienie zostałopodzielone na poszczególne sekcje. Każda z nich prezentuje pewien określony aspekt kodu.

%�����������������������������������������!

Motywacja do używania klas zagnieżdżonych wydaje się być dosyć niejasna, zwłaszczaże każda zagnieżdżona klasa może być technicznie zaimplementowana jako zwykła kla-sa. Istnieją pewne ściśle określone powody do wprowadzania klas zagnieżdżonych, jed-nak jest ich zaledwie kilka i będziesz się z nimi bardzo rzadko spotykał.

Page 52: Visual Basic .NET. Księga eksperta

272 Część II � Zaawansowane programowanie zorientowane obiektowo

Aby zademonstrować techniczne aspekty wprowadzania klas zagnieżdżonych, napisa-łem przykładowy program TrafficSignal.sln. Światła sygnalizacji świetlnej — czerwonena górze, żółte w środku i zielone na dole — idealnie nadają się na elementy klasy za-gnieżdżonej. Jest raczej mało prawdopodobne, że spotkasz na ulicy pojedynczy sygnałświetlny — tylko w jednym kolorze — którego stan będzie zależeć on innych światełnie towarzyszących jemu. (Może istnieć pojedyncze żółte światło pulsujące, jednak w tymprzypadku można je zaimplementować jako element osobnego sygnału świetlnego. Przy-kład ten ilustruje wątpliwości, jakie często można napotkać przy korzystaniu z klas za-gnieżdżonych: za każdym razem, kiedy korzystasz z tego typu klasy, znajdzie się wy-jątek, który sugeruje zrezygnowanie z zagnieżdżania).

��#��� zawiera trzy egzemplarze klasy ?�#��. Stanowią one sens jedynie jako całość (takzakładamy w naszym przykładzie), potrzebujemy więc więcej niż jedno światło. Wpro-wadzimy je zatem jako klasę zagnieżdżoną i utworzymy trzy egzemplarze tej klasy.

� �������������������

Klasa ��#��� reprezentuje trzystanowe, czerowno-żółto-zielone światło sygnalizacji dro-gowej. ��#��� będzie zdefiniowany tak, aby rysował na ekranie wyjściowym swój sym-bol za pomocą obiektu &������� oraz będzie reprezentować poszczególne stany za po-mocą odpowiednich kolorów.

Klasa ��#��� posiada tablicę trzech obiektów ?�#��, których stany są ze sobą odpowied-nio powiązane i będą się zmieniać tak, jak zmieniają się światła w rzeczywistości. Dwasygnały z różnymi stanami są pokazane na rysunku 7.4.

���������Dwa egzemplarzeklasy Signal

z rozwiązania

TrafficSignal.sln

Wszystkie składowe klasy ��#��� są zdefiniowane w wierszach 1. – 146. wydruku 7.7.W poniższych podrozdziałach omawiam poszczególne aspekty tej klasy.

������� ����!� ��&�������� ������������������&���*� ����&�

Pierwszą rzeczą, jaką zauważysz na wydruku 7.7, jest to, że wykorzystana została funk-cja skracania kodu za pomocą dyrektywy C9�#���. Długim, skomplikowanym wydrukom

Page 53: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 273

klas typu ��#��� na pewno przyda się trochę uporządkowania. Górna połowa wydrukuzawiera składowe klasy ��#���, a dolna — począwszy od wiersza 149. — definiuje kla-sy zagnieżdżone. Przez dodanie dyrektywy C9�#��� możesz zwijać i rozwijać fragmentykodu, ułatwiając sobie tym samym pracę z programem.

Warto również deklarować egzemplarze w kolejności ich ważności. Konsumentów inte-resują tylko składowe ����, więc je umieść jako pierwsze w kodzie. Generalizatorówdotyczą również składowe ��������, więc one niech będą po publicznych. Na końcuumieść składowe ������, które dostępne są jedynie twórcy klasy.

Takie uporządkowanie na pewno się przydaje, jednak w przypadku stosunkowoprostych i krótkich klas składowe mogą być umieszczane w kolejności ich tworzenia,bez zachowywania jakiejś szczególnej kolejności.

Jako ostatnie i najmniej znaczące w wydruku definiujemy klasy zagnieżdżone. Gdybybyły one istotne dla konsumentów, nie byłyby klasami zagnieżdżonymi.

!� ���� ���� ������������������

Klasa ��#��� posiada trzy egzemplarze klasy ?�#�� i obiekt �����. Z tego powodu kon-struktor, destruktor oraz metody $������ zostały dodane do klasy ��#���. Konstruktori $������ zostały zdefiniowane odpowiednio w wierszach 11. – 16. i 18. – 24. Dla pew-ności, fragment ten został przedstawiony na wydruku 7.8. Metoda �����������������służy do wywoływania metody $������ — wiersze 39. – 41. — i nie została poniżejprzedstawiona.

�� ������Konstruktor oraz metoda Dispose klasy Signal

""#������ ����B�=���2���/� �� ��/� �������"$#������/� ��5�/� �"%#������������9�������")#��������@�-������"*#�������������������"+#���������",#".#������ ����(��'�����"0#���������� �(���� ����������5������$1#�����67��(�����������������$"#�����(����5����$$#�����J�����������$%#�����-���''����������>�����$)#���������

Konstruktor ���3�� deleguje wszystkie swoje zadania do dobrze znanych metod, któ-rych nazwy bezpośrednio „mówią”, co jest w danej chwili robione. Inną strategią jestdodanie metody !��������� i wydelegowanie do niej całości kodu inicjującego; techni-ka ta umożliwi ponowne zainicjowanie obiektu bez konieczności tworzenia nowegoobiektu. W konstruktorze tym: określono, że ograniczający prostokąt jest przechowy-wany w polu, ustawiono światła ?�#��� na określonej pozycji, włączono światło zieloneoraz utworzony został wątek �����.

Page 54: Visual Basic .NET. Księga eksperta

274 Część II � Zaawansowane programowanie zorientowane obiektowo

Metoda $������ wykorzystuje zmienną lokalną w roli wartownika. Dzięki niemu drugiei kolejne wywołanie $������ nie wykonuje żadnych czynności. Za pierwszym razemnatomiast metoda usuwa wszystkie wątki, które kontrolują stan świateł i powstrzymujesystemowy odzyskiwacz pamięci. Same światła nie są zwalniane, gdyż zostały utwo-rzone na zewnątrz konstruktora w wierszach 73. i 74. poprzez element inicjujący tablicę.

+���� ���#��������

W wierszu 15. (zobacz wydruk 7.7 i 7.8) wywoływana jest metoda ����� �����. Wszystkiemetody zarządzające wątkami zostały pokazane na wydruku 7.9, będącym fragmentem koduz wydruku 7.7.

�� ������Metody obsługujące wątki w klasie Signal

)%#������� ���������������������))#�������������5�B�=������������������ ������@7�B����������)*#�������������6��� F������5����)+#������������������),#���������).#)0#������� ��������������������*1#��������������������*"#���������*$#*%#������� ����������'��������*)#������������� ������**#�������������;�����*+#���������*,#*.#������� �������J�����������*0#��������'��������+1#�������������5�B������+"#���������

W wierszu 44. tworzony jest egzemplarz klasy �����%' �������#' �����. Konstruktorklasy ����� pobiera adres procedury (������)�; procedura ta jest w miejscu, gdziewątek się rozwidli podczas swojego startu. Wiersz 45. oznacza, że wątek staje się wąt-kiem w tle, umożliwiając aplikacji wyjście i zatrzymanie wątków sygnału. W wierszu46. wywoływana jest metoda �������#���, która załącza sygnał świetlny poprzez uru-chomienie procedury z wiersza 49. Wraz z wywołaniem metody $������ wywoływanajest D��� �����. Z wydruku można wywnioskować, że D��� ����� uruchamia ������"#��� i zwalnia obiekt wątka poprzez przypisanie go do 3�����#. ������#��� wywołujemetodę � �����'(����, a � �����'2��� czeka na zakończenie działania wątku. � ���"��'(���� unicestwia wątek poprzez wywołanie wyjątku �����(�����*�������, któregonie da się przechwycić; wyjątek ten umożliwia wykonanie wszystkich bloków �������,potrzebne jest więc wywołanie 2���, aby upewnić się, że wątek został zakończony.

Wielowątkowość jest całkowicie nowym zagadnieniem w Visual Basic .NET. Jeśli wcze-śniej nie programowałeś w języku umożliwiającym obsługę wielu wątków, może to byćdla Ciebie nie lada wyzwaniem. Klasa ����� i programowanie wielowątkowe w VisualBasic .NET zostały dokładnie omówione w rozdziale 14, „Aplikacje wielowątkowe”.

Page 55: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 275

������ ����* �������������������� �������� ��

Obiekty ��#��� są rysowane dla każdej kontrolki, która przekaże swój obiekt &�������metodzie ��#���'$���. (W rzeczywistości sygnał powinien być kontrolką, ale odeszli-byśmy znacząco od tematu klas zagnieżdżonych, dyskutując teraz o tym). Przyjrzyj sięponiższym fragmentom kody z wydruku 7.7:

��+#������ ����(��=���2���-��'�� � ��-��'�� ����,#�����-��'�� �����/� �����������������=�<�/� ����.#�����(��=9������-��'�� ���0#�������������+%#������� �������(��=9��������2���-��'�� � ��-��'�� ���+)#�����(�&�6� ��6�������+*#���������6�5�1�����9������-��C''�������1��++#��������9������6��(��=�-��'�� ��+,#�����B����+.#������������"+"#��������� ������ �����-��������� ������"+$#�������67�������������"+%#���������/��������� �����"�"+)#�����������"+*#���������/��������� �����1�"++#�����������67"+,#����������� ����"+.#"+0#�������� ����(��=���2���-��'�� � ��-��'�� ��",1#�������-��'�� ���������'���-��������<�/� ��","#�����������

W tych trzech metodach zrealizowane jest rysowanie obiektów. W wierszach 6. – 9. ��"#���'$��� rysuje ��#��� jako 9�����#�� (prostokąt) i wywołuje ��#���'$���?�#��� w celudodania do prostokąta świateł. $���?�#��� wykorzystuje pętlę do narysowania każdegoze świateł, przy okazji prezentując dywersyfikację zadań oferowanych przez klasy i klasyzagnieżdżone. ?�#��'$��� wywołuje &�������'����������� (używając argumentu &��"����), używając 9��� jako obszaru ograniczającego dane światło oraz ?�#��'&��+���do określenia rodzaju pędzla na podstawie aktualnego stanu światła. Gdy wywoływanajest metoda rysująca, zajmuje się ona wyłącznie obiektami ��������, +����� i 9���,a nie zmianą poszczególnych stanów czy obliczaniem granic obszarów.

Wiersze 163. i 165. wykorzystują polimorficzną właściwość +���(���� w celu uzyska-nia poprawnej tablicy obiektów pędzla na podstawie egzemplarza lampy. Jeśli ������0�����, zwracany jest pędzel wyłączony; w przeciwnym wypadku właściwość zwrócipędzel o określonym przez egzemplarz lampy kolorze.

Rozdział 10., „Dziedziczenie i polimorfizm”, zawiera bardziej obszerną dyskusję natemat dziedziczenia i zagadnień związanych z polimorfizmem; przedstawia równieżsposoby definiowania i implementacji interfejsów.

Page 56: Visual Basic .NET. Księga eksperta

276 Część II � Zaawansowane programowanie zorientowane obiektowo

� ����������#��������������#������&��!�

?�#��, &����?�#��, E�����?�#�� oraz 9��?�#�� są klasami zagnieżdżonymi. ?�#�� wyko-rzystuje modyfikator ���!������. Klasa ?�#�� jest przykładem abstrakcyjnych klas ba-zowych w Visual Basic .NET, co oznacza, że ma ona być raczej potomkiem i nie ma byćutworzona bezpośrednio. Musi korzystać z modyfikatora ���!������, ponieważ dekla-ruje abstrakcyjną właściwość:

���� �������@!�������/���@������'��������� ������� ��������

Zauważ, że +���(���� w wierszach 158. i 159. na wydruku 7.7 nie posiada bloku procedu-ry; jest to wyłącznie deklaracja. Instrukcje z ���)������� odnoszą się do wirtualnych i abs-trakcyjnych składowych, co oznacza, że muszą być implementowane w klasie potomnej.

Wirtualne, abstrakcyjne składowe są analogią do deklaracji interfejsu w klasach COM.&����?�#��, E�����?�#�� i 9��?�#�� — każda z nich musi implementować właściwość+���(����, w przeciwnym razie będą wirtualne i abstrakcyjne.

Instrukcje deklarujące są wykorzystywane w celu pomocy przy wprowadzaniu klas po-tomnych. Metoda $��� klasy ?�#�� zależy od &��+���, a &��+��� w rezultacie zależyod tego, czy uda się uzyskać odpowiedni pędzel i kolor na podstawie stanu określonejlampy. W językach strukturalnych (lub niepoprawnie w językach obiektowych) ten ro-dzaj zachowania był implementowany z wykorzystaniem instrukcji ����.

$��������������������������������

Klasy świateł sygnalizacji same w sobie są łatwe do implementacji. Każde poszczegól-ne światło wymaga jedynie dziedziczenia z ?�#�� oraz zaimplementowania właściwościtylko do odczytu +���(����. Wydruk 7.10 przedstawia jedną z tych klas — 9��?�#��.(Treść wszystkich świateł różni się jedynie wartościami wykorzystywanymi do zaini-cjowania +���(����).

�� �������Sposób implementacji jednego ze świateł

",.#���G�Q�����P�P����F�����/��9����<��>���>� >��>�9����",0#�����!����������/��9����".1#�����6��������9����"."#".$#��������� ����@!��������/���@������'��������� ������� ��������".%#�������-��".)#�������������� �������� �������5�:�������-���<�A".*#������������������/��?".+#���������/���������".,#�����������-��"..#�����������'����".0#������������

W wierszu 182. wprowadzona jest chroniona, przesłonięta i tylko do odczytu właściwośćo nazwie +���(����. Statyczna tablica pędzli jest inicjowana pędzlami globalnymi zde-finiowanymi w obiekcie +�����. Klasa 9��?�#�� wykorzystuje pędzle koloru szaregoi czerwonego.

Page 57: Visual Basic .NET. Księga eksperta

Rozdział 7. � Tworzenie klas 277

Istnieje kilka sposobów, na jakie moglibyśmy zaimplementować kolorowe lampy sy-gnalizacji świetlnej. Moglibyśmy na przykład użyć jednej klasy ?�#�� i metod fabrycz-nych, które inicjują wartości pędzla na podstawie rodzaju światła; rodzaj ten mógłbybyć zdefiniowany z wykorzystaniem typu wyliczeniowego. W programowaniu, jak wewszystkich dziedzinach życia, musimy przyjąć pewien sposób postępowania. W tymrozdziale wybrałem podejście, które najlepiej obrazuje klasy zagnieżdżone. W rezulta-cie otrzymaliśmy ogólnie bardzo dobry kod.

�������������������'�� ��&��!�

W systemie produkcyjnym przykładowy program obsługi świateł sygnalizacyjnych nada-wałby się lepiej jako aplikacja niż komponent. Jeśli modelowałbyś światła miejskie, napewno chciałbyś jeszcze raz przemyśleć wszystkie wątki. W mieście wielkości Gliwicmiałbyś 40 wątków, ale w Warszawie komputer eksplodowałby, przełączając wszystkieniezbędne do prawidłowego funkcjonowania miasta wątki. W dodatku światła sygnali-zacyjne wymagają koordynacji. Lepszą implementacją byłby na przykład menedżerwątków, który koordynowałby światła na poszczególnych skrzyżowaniach oraz przy-dzielałby czasy trwania poszczególnym sygnałom.

W przypadku symulacji wizualnych aspektów zarządzania ruchem samochodowym na-leżałoby również dopracować grafikę naszej aplikacji i dołączyć inne rzeczy związanez tym zagadnieniem.

�����������������������

Do tej pory spotkałeś się już z wieloma przykładami tworzenia egzemplarzy klas. Jed-nakże ten rozdział jest pierwszym, w którym temat klas omawiany jest oddzielnie.Przyjrzyjmy się więc jeszcze raz składni tworzenia obiektów.

Klasy są określane mianem typów referencyjnych. Typy takie, w przeciwieństwie dotypów bezpośrednich, są tworzone poprzez deklarację zmiennej i użycie słowa 3��, a ponim nazwy klasy i nawiasów:

(�&����������� ��B�=��������

Przykład ten wygląda, jak gdybyśmy wywoływali procedurę o nazwie ����. Jest tojednak forma służąca do konstrukcji obiektu. W rzeczywistości kod taki wywołuje kon-struktora ���3��,. zdefiniowanego w klasie ����. Jeśli masz parametry, które chceszprzekazać do konstruktora, umieszczasz je w nawiasach przy nazwie klasy, cały czasjest to jednak wywoływanie ���3��, tym razem tylko przeciążonej. Składnia taka możewprowadzać małe zamieszanie. Oto przykład tworzenia egzemplarza klasy ��#��� z po-przedniego podrozdziału:

(�&� ������� ��B�=��������B�=�/� �������"1<�"1<�"11<�%11��

Jeśli procedura pobiera obiekt, rozważ możliwość utworzenia obiektu — tak jak 3��9�����#��,-/5�-/5�-//5�F//. — podczas wywołania procedury. Technika ta pomożew usuwaniu niepotrzebnych zmiennych tymczasowych.

Page 58: Visual Basic .NET. Księga eksperta

278 Część II � Zaawansowane programowanie zorientowane obiektowo

Powyższa instrukcja deklaruje i inicjuje egzemplarz klasy ��#���. Wywołuje ona kon-struktora ��#���'3��,., przekazując egzemplarz nowego prostokąta (zobacz wiersz 11. nawydruku 7.7.). Taki sposób wywoływania jest dość dziwny, jednak decyzje w tej spra-wie podejmował Microsoft podczas projektowania Visual Basic .NET.

W innych językach można spotkać inne formy konstruktorów i destruktorów. C++ używaoperatora ���, który może być przeciążony, przy czym konstruktor ma on taką samą na-zwę jak klasa, a nazwa destruktora jest również nazwą klasy, lecz poprzedzoną znakiemtyldy (G). Object Pascal korzysta z metod ����� i $������, ale w rzeczywistości kon-struktory i destruktory oznacza słowami kluczowymi ���������� i ���������.

�����������

Konstrukcja klasy różni się między VB6 a Visual Basic .NET. W VB6 klasy są interfej-sami i literalnie używają słowa ���������. Klasy Visual Basic .NET wykorzystują słów-ko ���� i umożliwiają dziedziczenie, cechę wcześniej niespotykaną. Ten rozdział jakopierwszy z rozdziałów tej książki podejmuje się przedstawienia bardziej zaawansowa-nych zagadnień.

Przedstawiono tu podstawowe sposoby definiowania klas, dodawania pól, właściwo-ści, zdarzeń i metod; pokazano, jak radzić sobie ze złożonością specyfikatorów dostę-pu i jak stosować modyfikatory. W tym rozdziale zostały pokazane zmiany wprowa-dzone w Visual Basic .NET do interfejsów, jak również sposoby implementacji metodinterfejsu i klas zagnieżdżonych. Dowiedziałeś się, jak korzystać z wielowątkowościi dziedziczenia.

Rozdziały 8., „Dodawanie zdarzeń”, i 9., „Delegacje”, rozszerzają przedstawione w tymrozdziale zagadnienia zdarzeń i delegacji, a rozdział 10., „Dziedziczenie i polimorfizm”,szczegółowo prezentuje dziedziczenie i polimorfizm. W rozdziale 12., „Definiowanieatrybutów”, dowiesz się, jak wydajnie wykorzystywać atrybuty.