C# i ASP.NET. Szybki start
-
Upload
wydawnictwo-helion -
Category
Technology
-
view
3.484 -
download
1
description
Transcript of C# i ASP.NET. Szybki start
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-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
C# i ASP.NET. Szybki start
C# to ca³kiem nowy jêzyk programowania zaprojektowany przez firmê Microsoft.
Wygl¹da on jak mieszanka C++ i Javy, jest jednak tak prosty jak Visual Basic.
Z jego pomoc¹ mo¿na tworzyæ aplikacje WWW i programy wyposa¿one w graficzny
interfejs u¿ytkownika. Jêzyk ten zwi¹zany jest z platform¹ .NET, umo¿liwiaj¹c¹
tworzenie zaawansowanych aplikacji biznesowych dzia³aj¹cych w �rodowisku
sieciowym, w tym tak¿e z technologi¹ budowania dynamicznych serwisów
internetowych ASP.NET. Programy dzia³aj¹ce na platformie .NET mo¿na pisaæ
w wielu jêzykach programowania, ale wiele wskazuje na to, ¿e w³a�nie C# stanie siê
najpopularniejszym z nich.
Ksi¹¿ka „C# i ASP.NET. Szybki start” jest doskona³ym podrêcznikiem dla
pocz¹tkuj¹cych programistów. Jak ka¿da pozycja z serii „Szybki start”, sk³ada siê
z kilkudziesiêciu rozdzia³ów, z których ka¿dy przedstawia kolejne kroki, które nale¿y
wykonaæ, by osi¹gn¹æ zamierzony cel. Dodatkow¹ zaletê stanowi¹ liczne ilustracje.
Opisano miêdzy innymi:
• Instalacjê niezbêdnego oprogramowania
• Sk³adniki jêzyka C#
• Instrukcje warunkowe i pêtle
• Pracê z ci¹gami znaków
• Programowanie obiektowe w C#
• Korzystanie z tablic i kolekcji
• Delegaty, zdarzenie, obs³ugê b³êdów
• Tworzenie dynamicznych serwisów WWW w jêzyku C#
Programista chc¹cy tworzyæ zaawansowane aplikacje internetowe ma wybór pomiêdzy
dwoma platformami: Java 2 EE Suna i .NET Microsoftu. Je�li wybierze tê drug¹, dziêki
ksi¹¿ce „C# i ASP.NET. Szybki start” szybko bêdzie móg³ tworzyæ funkcjonalne
aplikacje WWW w nowym, ekscytuj¹cym jêzyku C#.
Autor: Jose Mojica
T³umaczenie: Wojciech Moch (rozdz. 1 - 6),
Rados³aw Meryk (rozdz. 7 - 13)
ISBN: 83-7361-389-7
Tytu³ orygina³u: C# Web Development with ASP.NET:
Visual QuickStart Guide
Format: B5, stron: 456
Przyk³ady na ftp: 1127 kB
Spis treści
5
Spis tre
ści
Wstęp 11
Rozdział 1. Zaczynamy 23
Jak zdobyć C# ...........................................................................................24
Instalowanie IIS.........................................................................................26
Tworzenie projektu aplikacji sieciowej w Visual Studio .NET ................28
Uruchamianie projektów sieciowych za pomocą Visual Studio .NET........ 31
Pisanie prostej strony ASP .NET ..............................................................33
Wyszukiwanie błędów w aplikacjach ASP .NET .....................................35
Ręczne uruchamianie kompilatora ............................................................38
Kompilowanie i uruchamianie programów C# bez pomocy VS.NET ........ 39
Wyszukiwanie błędów w programach bez pomocy VS.NET ...................41
Rozdział 2. Składniki języka C# 43
Praca z elementami języka ........................................................................44
Pisanie kodu C#.........................................................................................48
Deklarowanie zmiennych ..........................................................................50
Definiowanie stałych.................................................................................53
Grupowanie stałych w typy wyliczeniowe................................................54
Deklarowanie funkcji ................................................................................56
Deklarowanie funkcji z parametrami ........................................................58
Zwracanie wartości funkcji .......................................................................62
Definiowanie klas......................................................................................64
Dodawanie klas do przykładowej aplikacji...............................................67
Tworzenie i stosowanie obiektów .............................................................68
Tworzenie obiektów w przykładowej aplikacji.........................................70
Włączanie definicji klas ze źródeł zewnętrznych......................................71
Grupowanie klas w przestrzeniach nazw ..................................................74
Dodawanie pól do klas ..............................................................................78
Inicjalizowanie pól w momencie ich deklarowania ...................................79
Dodawanie właściwości do klas................................................................80
Spis treści
Spis treści
6
Spis treści
Dodawanie metod do klasy .......................................................................86
Dodawanie składowych do klas przykładowego programu ......................89
Uruchamianie przykładowej aplikacji.......................................................90
Dodawanie komentarzy.............................................................................95
Kierunki parametrów w typach referencyjnych ........................................97
Rozdział 3. Wyrażenia warunkowe i pętle 99
Praca z pętlami i warunkami ...................................................................100
Porównywanie typów numerycznych .....................................................104
Porównywanie typów referencyjnych .....................................................105
Łączenie porównań .................................................................................109
Instrukcje warunkowe .............................................................................110
Sprawdzanie wielu warunków za pomocą instrukcji switch ...................112
Operator warunku....................................................................................114
Dodawanie instrukcji warunkowych do przykładowego programu........115
Stosowanie pętli while ............................................................................122
Stosowanie pętli do .................................................................................123
Stosowanie pętli for.................................................................................124
Zakończenie i kontynuacja pętli..............................................................126
Dodawanie pętli do przykładowego programu........................................129
Rozdział 4. Ciągi znaków 133
Przygotowanie komputera do pracy z ciągami znaków ..........................135
Praca z ciągami znaków ..........................................................................137
Inicjalizowanie ciągów znaków ..............................................................140
Porównywanie ciągów znaków...............................................................142
Łączenie ciągów znaków.........................................................................145
Określanie długości ciągu znaków..........................................................147
Porównywanie i łączenie ciągów znaków w przykładowej aplikacji........ 148
Tworzenie ciągów z pojedynczych znaków............................................151
Znaki specjalne........................................................................................154
Stosowanie ciągów literałów...................................................................156
Dostęp do poszczególnych znaków ciągu ...............................................158
Wyszukiwanie podciągów wewnątrz ciągów znaków ............................159
Pobieranie wycinka ciągu........................................................................160
Dzielenie ciągu znaków...........................................................................161
Składanie ciągów.....................................................................................163
Spis treści
7
Spis tre
ści
Zamiana liter na małe lub wielkie ...........................................................164
Formatowanie ciągów znaków................................................................165
Uruchomienie przykładowej aplikacji.....................................................166
Zamiana obiektów na ciągi znaków ........................................................171
Tworzenie ciągów znaków za pomocą klasy StringBuilder .....................172
Rozdział 5. Dziedziczenie klas 173
Praca z dziedziczeniem klas ....................................................................174
Dziedziczenie z innej klasy .....................................................................177
Udostępnianie składowych klas i ograniczanie dostępu do nich.............180
Rozbudowa przykładowej aplikacji ........................................................183
Ukrywanie metod klasy bazowej ............................................................188
Pokrywanie funkcji w klasie wywiedzionej ............................................190
Dodawanie standardowego klawisza do przykładowej aplikacji ............194
Stosowanie nowego klawisza na formularzu WorkOrder .......................197
Dodawanie funkcji, które muszą zostać pokryte.....................................200
Wymóg dziedziczenia .............................................................................201
Blokowanie dziedziczenia.......................................................................202
Rozdział 6. Składowe specjalne 203
Dodawanie wielu funkcji o takich samych nazwach,
czyli przeciążanie funkcji ........................................................................204
Definiowane funkcji o zmiennej liczbie parametrów .................................207
Dodawanie konstruktorów ......................................................................209
Wywoływanie konstruktora klasy bazowej.............................................210
Dodawanie finalizerów ...........................................................................212
Tworzenie bibliotek kodu za pomocą składowych statycznych..............213
Zmiana znaczenia operatora (przeciążanie operatorów) .........................216
Definiowanie równoważności klas przez przeciążenie
operatora równości ..................................................................................220
Definiowanie równoważności klas przez pokrycie funkcji Equals .........222
Praca ze składowymi specjalnymi...........................................................224
Rozdział 7. Typy 229
Działania z typami...................................................................................230
Uzyskiwanie typu klasy ..........................................................................234
Sprawdzanie zgodności typów ................................................................236
Spis treści
8
Spis treści
Konwersja jednego typu na inny .............................................................237
Rozwinięcie przykładowej aplikacji .......................................................240
Definiowanie reguł konwersji (przeciążanie operatora konwersji) ........... 246
Rozdział 8. Interfejsy 249
Działania z interfejsami...........................................................................251
Definiowanie interfejsów ........................................................................255
Niejawna implementacja składowych interfejsu .....................................257
Jawna implementacja składowych interfejsu ..........................................260
Usprawnianie przykładowej aplikacji .....................................................261
Wykorzystanie obiektów poprzez interfejsy ...........................................268
Rozpoznawanie interfejsu .......................................................................269
Wykorzystanie interfejsów do polimorfizmu..........................................271
Interfejs będący pochodną innego interfejsu...........................................272
Refaktoryzacja.........................................................................................274
Ponowna implementacja interfejsów w klasie pochodnej.......................275
Kończymy przykładową aplikację ..........................................................277
Rozdział 9. Tablice i kolekcje 279
Działania z tablicami i kolekcjami ..........................................................281
Tworzenie tablic wartości .......................................................................285
Tworzenie tablic typów referencyjnych ..................................................287
Poruszanie się po tablicy .........................................................................291
Inicjowanie elementów tablicy w miejscu ..............................................294
Tworzenie tablic wielowymiarowych .....................................................296
Usprawnianie przykładowej aplikacji .....................................................298
Odnajdywanie elementów tablicy
za pomocą wyszukiwania liniowego.......................................................... 301
Sortowanie tablic.....................................................................................304
Odnajdywanie elementów tablicy
za pomocą wyszukiwania binarnego.......................................................... 307
Klasy działające jak tablice (definiowanie indeksatorów) ......................309
Wprowadzenie indeksatorów do przykładowej aplikacji........................312
Kopiowanie tablic ...................................................................................313
Tworzenie list dynamicznych..................................................................314
Tworzenie kolejek ...................................................................................316
Spis treści
9
Spis tre
ści
Tworzenie stosów....................................................................................317
Tworzenie tabel mieszających.................................................................318
Przeglądanie elementów tabel mieszających...........................................320
Kończymy przykładową aplikację ..........................................................321
Testowanie kontrolki CodeGridWeb.......................................................323
Rozdział 10. Delegaty i zdarzenia 325
Działania z delegatami i zdarzeniami......................................................327
Deklarowanie delegatów .........................................................................330
Tworzenie i wywoływanie delegatów.....................................................331
Łączenie delegatów .................................................................................333
Odłączanie delegatów .............................................................................334
Deklarowanie i wyzwalanie zdarzeń.......................................................336
Deklarowanie zdarzeń przyjaznych dla WWW ......................................338
Subskrypcja zdarzeń................................................................................340
Asynchroniczne wyzwalanie delegatów .................................................342
Oczekiwanie na zakończenie działania delegatów asynchronicznych ...... 346
Pobieranie wyników działania delegatów asynchronicznych .................348
Kończymy przykładową aplikację ..........................................................350
Rozdział 11. Obsługa błędów 353
Wykonywanie działań z wyjątkami ........................................................354
Przechwytywanie wyjątków....................................................................360
Przechwytywanie wybranych wyjątków .................................................363
Uzyskiwanie informacji o wyjątku..........................................................366
Działania z łańcuchami wyjątków...........................................................368
Deklarowanie własnych wyjątków..........................................................372
Definiowanie komunikatów o błędach....................................................374
Zgłaszanie wyjątku..................................................................................375
Przechwytywanie i ponowne zgłaszanie wyjątków ................................376
Tworzenie łańcucha wyjątków................................................................377
Wprowadzanie kodu,
który wykonuje się przed zakończeniem działania funkcji .....................378
Zastosowanie słowa kluczowego using...................................................380
Wprowadzanie zabezpieczeń formularzy do przykładowej aplikacji........ 382
Obsługa nieobsłużonych błędów w aplikacjach WWW .........................385
Spis treści
10
Spis treści
Rozdział 12. Odbicia i atrybuty 389
Działania z odbiciami i atrybutami .........................................................390
Identyfikacja kompilata...........................................................................394
Działania z wyświetlanymi nazwami ......................................................395
Działania z ciągami znaków opisu ścieżek .............................................398
Dynamiczne ładowanie programu na podstawie nazwy wyświetlanej...... 399
Dynamiczne ładowanie programu na podstawie ścieżki dostępu ...........400
Tworzenie egzemplarza klasy w kompilacie...........................................401
Uzyskiwanie listy klas w kompilacie ......................................................403
Wyszczególnienie składowych klasy ......................................................404
Dynamiczne ustawianie lub pobieranie pól.............................................406
Dynamiczne wywoływanie metody ........................................................409
Kończymy zadanie pierwsze w przykładowej aplikacji..........................411
Stosowanie atrybutów kodu ....................................................................413
Definiowanie atrybutów..........................................................................414
Wyszukiwanie atrybutów w kodzie ........................................................417
Kończymy zadanie drugie w przykładowej aplikacji..............................420
Rozdział 13. Projekty WWW w języku C# 423
Tworzenie projektu DLL za pomocą Visual Studio .NET ......................424
Odwoływanie się do kodu DLL i jego wykonywanie .............................428
Udostępnianie bibliotek DLL do globalnego wykorzystania ..................429
Tworzenie serwisów WWW ...................................................................432
Wykorzystywanie serwisów WWW .......................................................436
Skorowidz 439
Interfejsy
249
Interfejsy
Interfejsy to typy pozwalające na definiowaniewielu klas spełniających podobne funkcje.Wyobraźmy sobie klasę ������. W klasie ������są takie metody, jak: ���, ����� ����,�������������� itp. Użytkownik jestzadowolony z klasy ������, ponieważ umożliwiamu ona dojazdy do pracy i z powrotem. W pewnymmomencie jego koledzy zaczęli jednak żartowaćz klasy ������, dlatego postanowił zastąpić jąklasą �������. Przed zastąpieniem klasy ������klasą ������� użytkownik chce mieć jednakpewność, że klasa ta spełnia co najmniej takiesame funkcje, co klasa Escort. Musi więcoferować metody ���, ����� ����,��������������. Wszystkie te działania mogąbyć wykonywane inaczej niż w klasie ������,ale ważne jest, aby istniały co najmniej takiesame metody. Ich zestaw nazywa się interfejsem.Interfejs może np. nosić nazwę ��� ����.Wszystkie samochody, aby mogły być taknazywane, będą musiały zawierać implementacjęinterfejsu ��� ���� (przynajmniej z naszegopunktu widzenia).
W świecie, w którym żyjemy, obowiązują zasadyinterfejsów. Implementacjami podobnychinterfejsów są, na przykład, ����. Wielu z nasoddycha i je (jeśli ktoś się z tym nie zgadza,proszę natychmiast przestać czytać tę książkę).Każdy egzemplarz klasy ���� może w innysposób oddychać lub jeść, ale, niezależnie od tego,takie firmy, jak np. McDonald będą mogły odnosićsukcesy tylko wtedy, gdy zostanie wykonanametoda ������ należąca do interfejsu ��������.
Interfejsy
Interfe
jsy
Rozdział 8.
250
W terminologii języka C# interfejsy są typami.W stosunku do definicji interfejsów w języku C++różnią się tym, że nie są to wyspecjalizowaneklasy. Są to natomiast oddzielne typy. Zgodniez podstawową definicją, interfejs jest zbioremdefinicji funkcji (tylko definicji, bez koduimplementacji). Funkcje te same w sobie niewykonują żadnych działań. Przypominająinterfejs �������� bez konkretnego egzemplarzaczłowieka — to tylko pojęcie, a nie rzeczywistaimplementacja. Aby można było skorzystaćz interfejsu, należy go zaimplementowaćw obrębie klasy. Kiedy klasa implementujeinterfejs, ogłasza wszem i wobec, że obsługujewszystkie zdefiniowane w nim metody. Jeżelisprzedawca używanych samochodów twierdzi,że jego towar jest implementacją interfejsu��� ����, to tak samo, jakby mówił, że zawieraco najmniej metody: ���, ����� ����,��������������. Jeżeli któraś z metodinterfejsu nie zostanie zaimplementowana,kompilator języka C# zgłosi błąd.
Zastosowanie interfejsów pozwala programistompisać kod wykorzystujący funkcje i nie martwićsię ich implementacją. Dzięki temu możnarozpocząć od jakiejś implementacji, a potemcałkowicie ją zastąpić bez koniecznościprzepisywania kodu. Sprawdza się to w przypadkuinterfejsu ��� ����. Kierowcy nie uczą sięprowadzenia konkretnego samochodu — uczą sięprowadzić dowolny samochód, ponieważ wszystkiesamochody realizują ten sam, podstawowy interfejs.
Posłużmy się, jako przykładem rzeczywistegozastosowania interfejsów, technologią ADO .NET,która pozwala na realizację połączenia z baządanych. Firma Microsoft, można w to wierzyćlub nie, nie ma zamiaru wymuszać użycia tylkojednej bazy danych. Zamiast zmuszać do użyciatego samego zestawu klas, zdefiniowała interfejsfunkcji umożliwiających zrealizowanie połączeniaz bazą danych. Producenci baz danych mają więcmożliwość napisania klas będących implementacjątego interfejsu. Idea kodowania z wykorzystanieminterfejsów polega na tym, że można zmienićwykorzystywany pakiet bazy danych bezkonieczności przepisywania aplikacji.
Interfejsy
Interfejsy
251
Działania z interfejsami
Jako przykładową aplikację w tym rozdzialenapiszemy moduł ASP .NET. Nie będzieto aplikacja bardzo rozbudowana, ale za to będzieją można wykorzystać w rzeczywistychaplikacjach (w tym rozdziale nie będzie aplikacjidotyczącej supermenów).
A zatem, czym jest moduł ASP .NET?Moduł jest klasą, która może przechwytywaćżądania dowolnych stron w aplikacji. Moduływykorzystuje się do wykonywania takichdziałań, jak np. testy zabezpieczeń. Mogą oneprzechwycić każde żądanie i albo je zatrzymać,albo kontynuować lub też zmodyfikowaćw pewien sposób. Moduły mogą takżewykonywać działania po obsłudze żądaniaprzez odpowiednią stronę. Programistomdoświadczonym w programowaniu aplikacjiWWW z pewnością pomoże wyjaśnienie,że moduły są odpowiednikiem filtrów IISw środowisku .NET.
Celem modułu, który utworzymy, będziedostarczenie wszystkim stronom informacjio rozmiarach obszaru klienta w przeglądarce.Obszar klienta w przeglądarce to miejsce,w którym jest wyświetlana strona WWW(wewnątrz okna przeglądarki, bez pasków menui stanu). Interesujące, że środowisko .NET nieprzekazuje tych wymiarów za pośrednictwemżadnej z właściwości. Można jednak uzyskaćte wielkości za pomocą skryptów działającychpo stronie serwera (VBScript lub JavaScriptdziałające na komputerze-kliencie, a nie naserwerze tak, jak strony ASP). Można zapytać,dlaczego interesują nas te wymiary? Otóż sąnam potrzebne, ponieważ czasami chcemyzastosować grafikę o mniejszych wymiarach,jeśli wymiary okna są mniejsze lub większychwymiarach, jeśli wymiary okna są większe.
Dzia
łania z in
terfe
jsami
Rozdział 8.
252
Rozwiązanie problemu jest następujące. Kiedyklient zażąda strony po raz pierwszy, modułzatrzyma żądanie i zwróci stronę z odpowiednimskryptem działającym po stronie klienta.Zadaniem skryptu będzie określenie wymiarówobszaru klienta. Skrypt zapisze wymiaryw ukrytym polu, a następnie zażąda natychmiasttej samej strony, której klient żądał poprzednio.Wysłanie skryptu działającego po stronie klientai zwrócenie pierwotnie żądanej strony powinnonastąpić na tyle szybko, aby użytkownik niczegonie zauważył. Za drugim razem, gdy modułotrzyma żądanie tej samej strony (teraz zażądajej skrypt działający po stronie klienta),moduł odnajdzie ukryte pola zawierającewymiary, utworzy niewielki obiekt służącydo przechowywania potrzebnych informacjii przekaże je do żądanej strony. Strona pobierzeobiekt z informacjami i zwróci wynik do klienta,który wykorzysta informacje o rozmiarze obszaruklienta. W naszym przypadku na stronie wymiarywyświetlone zostaną w polach tekstowych.
Aby napisać moduł:
1. Uruchom Visual Studio .NET (Start/Programy/Microsoft Visual Studio .NET).
2. Wybierz polecenie File/New/Project.Na ekranie pojawi się okno dialogoweNew Project.
3. W panelu Project Types po lewej stronieokna New Project kliknij folder Visual C#projects.
4. Zaznacz ikonę ASP .NET Web Applicationi zmień nazwę aplikacji na interfacesproject(rysunek 8.1).
5. Program Visual Studio utworzy nowy projekti otworzy formularz WebForm1.aspx.
6. Zmień nazwę formularza na dimensions.aspx.W tym celu wybierz polecenie View/SolutionExplorer z górnego paska menu.
Rysunek 8.1. Do utworzenia modułu potrzebny jesttylko projekt biblioteki, a nie cały projekt WWWASP .NET. Jednak utworzenie projektu WWWASP .NET pozwala na napisanie i przetestowaniemodułu w jednym projekcie
Działania z interfejsami
Interfejsy
253
Rysunek 8.2. Zmiana nazwy pliku nie powinnasprawiać teraz żadnych problemów
Rysunek 8.3. Bardzo prosty formularz, który łatwoutworzyć od nowa. Zawiera dwie etykiety, dwa polatekstowe oraz jedno łącze
7. Kliknij prawym klawiszem myszy formularzdimensions.aspx i wybierz polecenieProperties. W tabelce właściwości,pokazanej poniżej na rysunku 8.2, zmieńwłaściwość FileName z WebForm1.aspxna dimensions.aspx.
8. Zmodyfikuj formularz dimension.aspxw taki sposób, aby wyglądał tak, jak formularzpokazany na rysunku 8.3. Oczywiście,w ręczne wykonanie tego zadanie trzebawłożyć wiele pracy. Zamiast tego możeszwprowadzić kod HTML bezpośredniow edytorze. Na rysunku 8.4, na następnejstronie, zaprezentowano kod HTML niezbędnydo utworzenia formularza. Aby bezpośredniowprowadzić kod HTML, kliknij przyciskHTML w oknie edytora. Alternatywniemożesz pobrać plik szkieletu dla tego projektu(patrz „Wskazówki” na następnej stronie).
Dzia
łania z in
terfe
jsami
Rozdział 8.
254
Wskazówki
� To, co do tej pory zrobiliśmy w przykładowejaplikacji, nie ma nic wspólnego z modułemużytkownika. Formularz projektowanyw tym podrozdziale zostanie użytydo przetestowania modułu. Kod modułuzostanie dodany natychmiast po tym, jakdowiemy się czegoś na temat implementacjiinterfejsów.
� Podobnie jak w przypadku innych projektóww tej książce, utworzenie projektu niejest konieczne do poznania pojęćzaprezentowanych w niniejszym rozdziale.
� Szkielety wszystkich projektów możnapobrać z witryny WWW WydawnictwaPeachpit pod adresem http://www.peachpit.com/vqs/csharp.
Rysunek 8.4. Kod HTML pokazany na tym rysunkumożna wykorzystać jako wzorzec. Dzięki formularzowimożliwe jest uzyskanie informacji o wymiarachi pozycji wszystkich elementów sterujących
������������������ �� ������������ ���������������� ������������������ ���� !��� ��������"�� ����� ��� !����� �#�������$� �% �&�'()*&�����'��+&�������������&���$� �%�,����&�����,'��+&��������-�)./�0."("01"12� 2 ��*�-��� &���������!� ����� $� �% ���������� ���� �������� ���� �� �� &�������������������������� ������ ������������������-�� 34"1+�56�%7%8�*�$(6����������������9:��8�����������������0."("016��������8�(0�6�;<�� ���������������� ���� �� �� &��������������������� ��������������,���6���&�������������������������� �'����� ������������������-�� 34"1+�56�%798�*�$(6����������������9=��8�����������������0."("016��������8�(0�6�<7�� ���������������� ���� �� �� &���������������������� ��������������,���6���&���������������������������� �������� ������������������-�� 34"1+�56�%7;8�*�$(6����������������>?��8�����������������0."("016��������8�(0�6�;@�� ���������������� ���� �� �� &������������,���6�������&����������������6����������� ���'����� ������������������-�� 34"1+�56�%7?8�*�$(6����������������>?��8�����������������0."("016��������8�(0�6�@>�� ���������������� ���� �� �� &������������,���6�������&����������������������������� A.�! ������������������-�� 34"1+�56�%7:8�*�$(6����������������>=��8�����������������0."("016��������8�(0�6�%%7�� ���������������� ���� �� �� ����������������1�������B � ������������� &������������������ �����������������,���6�-�� �A&���������,!� �&�����,���-&�,'()*&
Działania z interfejsami
Interfejsy
255
Rysunek 8.5. Składowe interfejsu to tylko definicje,które nie zawierają kodu. W definicjach nie stosujesię także modyfikatorów dostępu — wszystkiemetody interfejsu są publiczne
���������������"'���C����� ���1����C����8�D��,,właściwość tylko
�������������������������,, do odczytu
�����������E��������F8�,,metoda
��������G �����EF8�������,,metoda
D
Definiowanie interfejsów
Interfejsy definiuje się za pomocą słowakluczowego ���������. Dla interfejsów możnadefiniować metody, właściwości, delegaty,zdarzenia itp. Każdy z elementów wewnątrzinterfejsu musi być jednak tylko deklaracjąelementu i nie może zawierać implementacji.
Aby zdefiniować interfejs:
1. Wpisz słowo kluczowe ������ lub ��������,w zależności od zasięgu, jaki ma miećinterfejs.
2. Wprowadź słowo kluczowe ���������,a po nim spację.
3. Wpisz nazwę interfejsu.
4. Otwórz nawias klamrowy .
5. Wprowadź definicje składowych (tabela 8.1).
6. Zamknij nawias klamrowy ! (rysunek 8.5).
Defin
iowanie in
terfe
jsów
Tabela 8.1. Składowe interfejsu (składowe, któremożna wprowadzić do definicji interfejsu)
Nazwa Przykład
Metoda �� ���)�����EF8
Właściwość ������C����8����D
Właściwość tylko
do odczytu������C���8D
Indeks �������H������IC���8����6D
Zdarzenie ���������'��� 0���A8
Rozdział 8.
256
Wskazówki
� Wszystkie metody interfejsu z definicji sąpubliczne — w definicji metody nie możnawprowadzić modyfikatorów dostępu(dotyczy to także modyfikatora ������).
� Danych typu interfejsu można użyćw definicjach parametrów lub zmiennych(rysunek 8.6). W przypadku interfejsównie można jednak tworzyć nowychegzemplarzy — na przykład nie możnanapisać ���"�#������.
� W interfejsach można przeciążać metody(rysunek 8.7).
� Jeżeli jakiś programista użyje interfejsu,najlepiej nie zmieniać jego definicji.W przeciwnym razie istnieje ryzyko,że napisany program przestanie działać.W takiej sytuacji najlepiej zdefiniować nowyinterfejs. Więcej informacji na ten tematznajdzie się w dalszej części tego rozdziału,w podrozdziale „Tworzenie interfejsówpochodnych od innych interfejsów”.
Rysunek 8.6. Po zdefiniowaniu interfejsu możnago wykorzystać jako typ danych w deklaracjachzmiennych lub parametrów
�����+��-J�����C���������(��A�EF����C�������������� ���8�������������� �����8����D
���������������2�(�+�� E������ �����F����C���������� ��4&���EF8����DD
Rysunek 8.7. Przeciążanie metod to możliwośćistnienia kilku metod o tej samej nazwie.Pamiętaj, że można to zrobić tylko pod warunkiem,że zmieni się liczbę parametrów lub zmodyfikujetyp jednego z nich
��������� !����"'���C������ ���1����C���8�D����,,właściwość tylko do odczytu
���������!��E��������F8�,,metoda
���������!��E�� ���!���(-��K���������F8����,,przeciążanie
D
Definiowanie interfejsów
Interfejsy
257
Rysunek 8.8. Implementacja interfejsu przypominadziedziczenie. W przypadku metody niejawnejwystarczy zaimplementować składowe interfejsujako metody publiczne
��������� !����"'���C������ ���1����C���8�D���������.���E��� ����� �F8D
������������� ���6�������C ������ ����" #�������C�������������������C������������ ��� � ��� 8��������D�����D
������ $��� �����%���� ����&����C��������!� E��� ������� �78������������� ���� �8������ LLF��������C����������'����������������������������'������������ ��8�����������������J�������� ���E �� ����M F8��������D����DD
Niejawna implementacjaskładowych interfejsu
Interfejsy są implementowane przez klasy.Zaimplementowanie interfejsu oznaczawprowadzenie kodu dla wszystkichzdefiniowanych w nim metod. Kompilatorwymusza wprowadzenie kodu dla wszystkichmetod bez wyjątku. Wynika to stąd,że programista wykorzystujący interfejsspodziewa się, że klasa implementującainterfejs będzie zawierać definicje wszystkichzawartych w nim metod. Istnieją dwamechanizmy implementowania interfejsóww klasie: mechanizm niejawny i jawny.Najpierw zaprezentujemy mechanizm niejawny.
Aby zaimplementować interfejsw sposób niejawny:
1. Po nazwie klasy, która będzie implementowaćinterfejs, wpisz dwukropek, a po nim nazwęinterfejsu, który będzie implementowany.
2. Wprowadź składowe odpowiadającewszystkim składowym interfejsu.
3. Oznacz metody implementacyjne jakopubliczne.
4. Wpisz kod składowych interfejsu(rysunek 8.8).
Niejawna im
plementacja
składowych
Rozdział 8.
258
Wskazówki
� Ten mechanizm implementacji interfejsucechuje wada polegająca na tym, że każdąmetodę implementacyjną należy oznaczyćjako publiczną.
� Aby zaimplementować więcej niż jedeninterfejs, należy oddzielić poszczególnenazwy interfejsu przecinkiem (rysunek 8.9).
Rysunek 8.9. Klasa Person implementujezarówno interfejs IHuman, jak i IManager.Zaimplementowanie interfejsu ustanawia relację„jest”. Innymi słowy, osoba (Person) jestczłowiekiem (Human) i menedżerem (Manager)
��������� !����"'���C������ ���1����C���8�D���������.���E��� ����� �F8D
��������� !����")���� C���������.�-0����-��E�� ������K��������"�B�N� �F8D
������������� ���6�������' �(���"�C ������ ����" #�������C�������������������C������������ ��� � ��� 8��������D�����D
������ $��� �����%���� ����&����C��������!� E��� ������� �78������������� ���� �8������ LLF��������C����������'����������������������������'������������ ��8�����������������J�������� ���E �� ����M F8��������D����D
������ $��� �����!�������%����" ����' ���� ��)�����&����C��������N����E"�B�N� �F��������C������������*��A0�� .����� E���F8��������D����DD
Niejawna implementacja składowych
Interfejsy
259
Rysunek 8.10. W powyższym kodzie zdefiniowanoklasę Person, która implementuje interfejs IHuman.Następnie, biorąc pod uwagę to, że nie wszystkieosoby są menedżerami, zdefiniowano klasęopisującą menedżerów. Jednak, ze względu na to,że menedżerowie są ludźmi (persons), klasata dziedziczy wszystkie składowe klasy Person(zasada dziedziczenia). Na końcu znajduje sięimplementacja interfejsu IManager
��������� !����"'���C������ ���1����C���8�D���������.���E��� ����� �F8D
��������� !����")���� C���������.�-0����-��E�� ������K��������"�B�N� �F8D
������������� ���6�"'���C������������ ���1�������C�������������������C������������ ��� � ��� 8��������D�����D
���������������.���E��� ����� �F����C��������!� E��� ������� �78������������� ���� �8������ LLF��������C����������'����������������������������'������������ ��8�����������������J�������� ���E �� ����M F8��������D����DD�����������)���� �6�*����' �(���"� ������ $��� �����!�������%����" ����' ���� ��)�����&����C��������N����E"�B�N� �F��������C������������*��A0�� .����� E���F8��������D����DD
� Jeżeli klasa jest pochodną innej klasy(nie interfejsu), najpierw należy wymienićklasę, która nie należy do interfejsu,a następnie implementowane interfejsy.Wszystkie te elementy trzeba oddzielićprzecinkami (rysunek 8.10).
Niejawna im
plementacja
składowych
Rozdział 8.
260
Jawna implementacjaskładowych interfejsu
Podczas implementowania interfejsu przezwprowadzanie składowych publicznychpowstaje problem polegający na tym, że czasamidwa interfejsy zawierają metodę o takiej samejnazwie i takich samych parametrach,ale konieczne jest zaimplementowanie tychmetod na dwa różne sposoby. W przypadkuzastosowania metody niejawnej jedna metodapubliczna będzie stanowiła implementacjęmetod o takiej samej nazwie i tym samymzbiorze parametrów dla wszystkich interfejsów.Metoda jawna umożliwia poinformowaniekompilatora o tym, którą metodę, któregointerfejsu mieliśmy zamiar zaimplementować.
Aby jawnie zaimplementowaćinterfejs:
1. Po nazwie klasy, która będzie implementowaćinterfejs, wpisz dwukropek, a po nim nazwęinterfejsu, który będzie implementowany.
2. Wpisz typ zwracanej wartości dla składowejinterfejsu.
3. Wpisz �$����������%��&������������%��.Mówiąc inaczej, wpisz nazwę interfejsu,po nim kropkę, a po niej nazwę metodyinterfejsu.
4. Wprowadź parametry składowej interfejsu.
5. Wpisz kod składowej interfejsu (rysunek 8.11).
Wskazówka
� Wszystkie metody implementowane w tensposób są prywatne. Nie można wprowadzićmodyfikatora dostępu na początku definicji.
Rysunek 8.11. W przypadku jawnegoimplementowania interfejsu nie wprowadza sięmodyfikatorów dostępu. Należy wpisać nazwęinterfejsu, po nim kropkę, a po niej nazwę metody
��������� !����"'���C������ ���1����C���8�D���������.���E��� ����� �F8D
������������� ���6�"'���C ����" ������+#�������C�������������������C������������ ��� � ��� 8��������D�����D
$��� ������+�����%���� ����&����C��������!� E��� ������� �78������������� ���� �8������ LLF��������C����������'����������������������������'������������ ��8�����������������J�������� ���E �� ����M F8��������D����DD
Jawna implementacja składowych
Interfejsy
261
Usprawnianieprzykładowej aplikacji
Teraz, kiedy wiemy już, w jaki sposób definiujesię interfejsy oraz jak należy implementowaćinterfejsy za pomocą klas, czas usprawnićprzykładową aplikację. Dokładniej rzecz ujmując,zdefiniujemy klasę, która będzie służyć jakomoduł użytkownika. Aby przekształcić klasęw moduł, należy zaimplementować w niejinterfejs ����� &'��&�(��������. Jegozaimplementowanie nie jest trudne — zawieratylko dwie metody: ���� i )������. ŚrodowiskoASP .NET wywołuje metodę ���� w momencie,gdy moduł jest po raz pierwszy ładowanydo pamięci. Metoda )������ wywoływana jestw momencie usuwania modułu z pamięci.Jedyna trudność polega na wykorzystaniuzdarzenia. Zdarzenia zostaną opisanew rozdziale 10. „Delegaty i zdarzenia”.
Nie zamierzamy poświęcać w tym rozdzialewiele miejsca na tłumaczenie, czym jestzdarzenie. Na razie wystarczy, abyśmy wiedzieli,że zdarzenie jest metodą wywoływaną w wynikudziałania. Implementacja zdarzeń pod wielomawzględami przypomina implementacjęinterfejsów. Różnica polega na tym, że interfejsmoże zawierać kilka metod, natomiast zdarzeniezawiera tylko jedną metodę. Przykłademzdarzenia jest kliknięcie przycisku. Klasa żądaod zdarzenia ����� informacji od przyciskuformularza. Kiedy użytkownik kliknie przycisk,serwer informuje klasę, że miało miejscezdarzenie. Moduł można wykorzystaćnp. do nasłuchiwania wystąpienia zdarzenia*�+��,�-����. Środowisko ASP .NET wyzwalato zdarzenie za każdym razem, gdy przeglądarkaklienta zażąda strony.
Usprawnianie przy
kładowej a
plik
acji
Rozdział 8.
262
Aby zdefiniowaćklasę modułu użytkownika:
1. Z paska menu wybierz polecenie Project/Add class. Wpisz custommodule.cs jakonazwę klasy i wciśnij Enter (rysunek 8.12).
2. W górnej części kodu modułu, poniżejwiersza o treści ����+"����� , wpisz wiersz����+"����� &'��.
3. W wierszu w postaci: ������"���������� ���� dodaj na końcu: �(��������tak, aby wiersz ten przyjął postać: �����������"����� ����."�(��������.
4. Teraz trzeba trochę „pooszukiwać”.W systemie Visual Studio .NET znajduje siękreator pozwalający na łatwą implementacjęinterfejsu. Z menu wybierz polecenieView/Class View.
5. W oknie Class View rozwiń folderinterfacesproject/custommodule/Bases and
interfaces. Kliknij prawym klawiszem myszyIHttpModule i z rozwijanego menu wybierzAdd/Implement Interface (rysunek 8.13).
Rysunek 8.12. Wszystkie właściwości funkcjonalnemodułu użytkownika zostaną zaimplementowanew klasie custommodule. Dzięki wykorzystaniu oknadialogowego pokazanego na rysunku użyjemykreatora do wygenerowania szkieletu klasy
Rysunek 8.13. Kreator implementacji interfejsuwykorzystuje mechanizm niejawnej implementacji.Dla każdej składowej interfejsu definiowane sąelementy publiczne
Usprawnianie przykładowej aplikacji
Interfejsy
263
Rysunek 8.14. Interfejs IHttpModule spełniadwie funkcje. Po pierwsze, informuje środowiskoASP .NET, że klasa jest modułem użytkownika.Po drugie, środowisko zyskuje możliwośćpoinformowania klasy, kiedy moduł jest ładowanypo raz pierwszy (metoda Init) oraz kiedy nie jest jużpotrzebny (metoda Dispose)
�����.-����8�����.-��������8
������������ !����� �#���C���,,,������� -&
���,,, Ogólny opis modułu custommodule
���,,,��,����� -&��������������������������6�"'���)�������C�����������������������EF������C���������,,���������,, DO ZROBIENIA: Tutaj należy
���������,,wprowadzić logikę konstruktora
���������,,������D
,�"��� �������������� �� �����(����� ������ $��� ����%������+���+����-���������� �������& . /
������ $��� 0������%& . / ,����"�������DD
6. Kreator spowoduje dodanie namiastekmetod ���� i )������. Kod przyjmie postaćwidoczną na rysunku 8.14.
7. Dodaj do klasy metodę *�+��,�-����(rysunek 8.15).
Rysunek 8.15. Metoda BeginRequest nie jest częściąinterfejsu IHttpModule. Jest to zdarzenie zdefiniowanedla klasy HttpApplication, informujące o tym,że występują żądania do dowolnej ze stron w aplikacji
�����.-����8�����.-��������8
������������ !����� �#���C,,,������� -&
���,,, Ogólny opis modułu custommodule
���,,,��,����� -&��������������������������6�"'���)�������C�����������������������EF������C���������,,���������,, DO ZROBIENIA: Tutaj należy wprowadzić
���������,,logikę konstruktora
���������,,������D
������� �����"������������!�"'���)��������������������������"��E.-���������'�������������������F������C������D
�����������������+������EF������C������D��������� ����
$��� 1�"��2�3����%��4��� �����' !$���-"� �"�& . /���DD
Usprawnianie przy
kładowej a
plik
acji
Rozdział 8.
264
8. W metodzie ���� wprowadź kod wiążącyzdarzenie *�+��,�-���� z metodą klasy*�+��,�-���� (rysunek 8.16). Nie martw się,jeżeli na razie kod ten jest niejasny, jegoszczegółowe wyjaśnienie znajdzie sięw rozdziale 10. „Delegaty i zdarzenia”.
Rysunek 8.16. Zwróć uwagę, że w celu powiązaniazdarzenia klasy z metodą do zdarzenia odwołujemysię w taki sposób, jakby było ono właściwościąobiektu (obiekt.nazwazdarzenia), następnieużywamy operatora += i przypisujemy mu nowyobiekt (delegat). Metodę przekazujemy jakoparametr konstruktora obiektu
�����.-����8�����.-��������8
������������ !����� �#���C���,,,������� -&
�������0�O-����������P����������������,,,��,����� -&��������������������������6�"'���)�������C�����������������������EF������C���������,,�����������DO ZROBIENIA: Tutaj należy
���������,,wprowadzić logikę konstruktora
���������,,������D
������� �����"������������!�"'���)��������������������������"��E.-���������'�������������������F������C �������+1�"��2�3���� 56 ��� !$���������%1�"��2�3����&7������D
�����������������+������EF������C������D��������� ����
�����������G���J�Q����E��#�������� K����������� ���� ��F������C������D���DD
Usprawnianie przykładowej aplikacji
Interfejsy
265
Rysunek 8.17. Doceń piękno literałów znakowych.Zwróć uwagę, jak łatwo — korzystając z literałówznakowych — można umieścić znaki końca wierszaw ciągu znaków. Po prostu formatujemy ciągznaków, tak jak chcemy, umieszczając gdzie należyznaki końca wiersza
�����������"��E.-���������'������������������FC�����������G���J�Q�����L���N����'��� EG���J�Q����F8 ����" ���� 6 89 :����; <��������+++ :����� ���"��"�6$������; ��� =��0���������%& 0�� ����������� 0�� ���������"��
����������� 6 ��������+����+>���������� ���������"�� 6 ��������+����+>��������"�� ��������+�����+���0���������+?���� 6����������� @ 99799 @ ���������"�� @ 99799 ��������+�����+������ !�� ��� :A�����; :���� ��B��� 699=��0���������99; :��� ����699�����99 ������699*��C99 ������ 6 99.D/99; :�;:����� ����699������99 ����699���0���������99 ���699ED99;:A�; :A���; :A����; :A����;97
�������+-����������F9GG0����$��C(B9H6����7D
9. Wprowadź kod w metodzie ���� w celuutworzenia ciągu znaków stanowiącegoskrypt działający po stronie klienta i zapiszgo w obiekcie #����������. Pamiętaj,że obiekt #���������� jest dostępnyna wszystkich stronach i dla każdegoklienta (rysunek 8.17).
Usprawnianie przy
kładowej a
plik
acji
Rozdział 8.
266
10. Teraz, w treści metody *�+��,�-���� wpiszkod pokazany na rysunku 8.18. Zadaniemtego kodu jest sprawdzenie, czy są dostępneinformacje o wymiarach. Informacjete powinny być dostępne za pośrednictwempola ukrytego. Jeżeli pole tekstowe nie istnieje,moduł zablokuje żądanie strony i wyśleskrypt działający po stronie klienta. Skryptzarejestruje wymiary okna w ukrytym polui natychmiast zażąda strony ponownie. Modułsprawdzi, czy pole tekstowe istnieje i, jeżeliistnieje, wprowadzi wymiary do obiektu ��� (więcej informacji na ten temat znajdzie sięw ramce na następnej stronie).
Wskazówki
� Kod zaprezentowany w tym podrozdzialeto kompletny kod potrzebny do utworzeniamodułu użytkownika. Jednak moduł ten niebędzie działać dopóty, dopóki nie uzupełnimyprzykładu kodem pokazanym w dalszej częścitego rozdziału.
� Kreator implementujący interfejsy wprowadzakod /��+���"� ��� ��������"��"�(��������na początku bloku metod implementacyjnychoraz /����+��� na końcu tego bloku.Te instrukcje nie dotyczą bezpośredniokompilatora. Umożliwiają one uzyskanierozwijanego kodu w edytorze. Jak możnazauważyć, w edytorze pojawi się znak minusz lewej strony deklaracji regionu (rysunek 8.19).Kliknięcie znaku minus w edytorze spowodujeukrycie kodu umieszczonego w obszarzei zastąpienie znaku minus plusem(rysunek 8.20). Kliknięcie znaku plusspowoduje ponowne pojawienie się kodu.
Rysunek 8.20. Kliknięcie znaku minus powodujerozwinięcie kodu obszaru i wyświetlenie opisuza słowem #region, umożliwiającego identyfikacjękodu. Słowo kluczowe #region w kodzie nie ma żadnegoznaczenia funkcjonalnego. Jest ono wykorzystywanewyłącznie przez edytor, zatem, jeżeli komuś wydaje sięniepotrzebne, może je usunąć
Rysunek 8.18. Na tym rysunku znalazł się kod,który wymaga wyjaśnienia. Szczegółoweinformacje na jego temat można znaleźć w ramcept. „Szczegóły zdarzenia BeginRequest”
�����G���J�Q����E��#�������� K������ ��� ��FC =����� " 6 %=�����&�����7 ����" ���������� 6 "+2�3����+I��F9���0���������9H7 �� %���������� 66 ���� JJ ���������� 66 99& . ����" ���� 6 %����"&"+>������+ �-����������F9GG0����$��C(B9H7 ����" ���)� 6 ����"+I����%����' "+2�3����+)�+-�������*���&7 "+2�������+����%���)�&7 "+>�������2�3����%&7 / ���� �� %����������+�������%9>����������9& 66 KL& . ����"FH ���� 6 ����������+�����%M7M&7 ��� ����������� 6 ������+>��$��+ C����NE%����FDH&7 ��� ���������"�� 6 ������+>��$��+C����NE%����FLH&7 "+>������+�����F9GG>����������9H 6 �����������7 "+>������+�����F9GG>��������"��9H 6 ���������"��7 /D
Rysunek 8.19. Instrukcja #region powodujedodanie obszaru rozwijanego kodu. Kiedy edytorwykryje dyrektywę #region, umieszcza znak minuspo lewej stronie okna kodu
Usprawnianie przykładowej aplikacji
Interfejsy
267
Szczegóły zdarzenia BeginRequest
W pierwszym wierszu metody *�+��,�-���� znajduje się instrukcja konwersji obiektu �����(pierwszy parametr metody) na obiekt 0�����. 0����� jest klasą generowaną przez kreatorpodczas tworzenia projektu ASP .NET. Jest to pochodna klasy (���#����������. Obiekt tej klasytworzy się za pierwszym razem, gdy dowolny klient skorzysta z dowolnej strony w aplikacji.
Z obiektu 0����� można uzyskać dostęp do innych obiektów — np. ,������� lub ,�-����.
W drugim wierszu kodu użyto obiektu 0����� do uzyskania obiektu ,�-����. Jak pamiętamy,obiekt ,�-���� umożliwia uzyskanie informacji na temat żądania klienta. Jeżeli skorzystamyz właściwości ��� , możemy uzyskać dostęp do ukrytego pola, które zostało utworzoneprzez skrypt działający po stronie klienta. Nazwa tego ukrytego pola to �1�)� �������.
W wierszu +&,�-����&��� 23�1�)� �������34 następuje pobranie tekstu z ukrytego pola.Jeżeli pole nie istnieje, zwrócony wynik będzie wartością ����. W przeciwnym razie będąto współrzędne obszaru klienta. Skrypt działający po stronie klienta zapisuje współrzędne
w postaci: szerokość;wysokość (np. 800;600). Jeżeli wynik wynosi ����, do klienta wysyłanyjest skrypt za pomocą funkcji ,�������&'����. Potem następuje wywołanie funkcji�� �����,�-����, której działanie polega na zatrzymaniu żądania strony. Jeżeli wymiary sądostępne, następuje rozbicie ciągu znaków o formacie szerokość;wysokość na dwie liczby
i konwersja tych liczb na typ ����+��. Wartości te są następnie umieszczone w obiekcie ��� �.
Do tej pory nie używaliśmy obiektu ��� �, ale przypomina on obiekty ������� oraz #����������.Ogólnie rzecz biorąc, jest to jeszcze jeden sposób utrwalania informacji. Różnica między
tymi obiektami polega na czasie dostępności informacji. W obiekcie ��� � informacje sądostępne tylko na czas trwania żądania klienta. W przypadku obiektu #���������� informacjesą dostępne tak długo, jak serwer WWW przetwarza aplikację i mają do nich dostęp wszystkie
klienty korzystające z aplikacji. Informacje zapisane w obiekcie ������� są dostępne na czastrwania programu, ale są one specyficzne dla każdego klienta. Obiekt ��� � istnieje tylkona czas żądania. Jeżeli zatem klient przechodzi z jednej strony na drugą, informacje zostająutracone. W ramach tego samego żądania moduł może jednak umieścić informacje
w obiekcie ��� � i strona będzie miała do nich dostęp przez odwołanie +&�����1�&��� �.
Usprawnianie przy
kładowej a
plik
acji
Rozdział 8.
268
Wykorzystanie obiektówpoprzez interfejsy
Kiedy programista zdefiniuje interfejsi zaimplementuje go jako konkretną klasę,może używać tej klasy poprzez interfejs.
Aby używać klasy poprzez interfejs:
1. Zdefiniuj zmienną typu interfejsu.Wpisz na przykład ����"5��.
2. Ustaw zmienną typu interfejsu na wartośćrówną klasie, która ten interfejs implementuje.Wpisz na przykład 6"���"������78(rysunek 8.21).
Wskazówka
� Nie można tworzyć egzemplarzy interfejsu.Interfejs jest typem abstrakcyjnym,co oznacza, że nie jest to klasa, którejobiekty można utworzyć. Zamiast tegotworzy się egzemplarze klasyimplementującej interfejs.
Rysunek 8.21. Chociaż typem zmiennej jest ICar,nie można napisać new ICar. Trzeba utworzyćegzemplarz klasy implementującej interfejs.Nie można tworzyć egzemplarzy interfejsu
��� !����"�� C����� ���J�EF8����� ���.���EF8����� �����-)����EF8D
��������� ��6�"�� C����������� ���J�EF���C������ ��� � R��S���A��T-�A�K�#�A������M 8���D����������� ���.���EF���C������ ��� � R�A���� T���� ��T������S����S������T�� T-��U 8���D����������� �����-)����EF���C������ ��� � R����V�-��� �����K�A�O T-������������ ���W��� 8���DD
�����+ ��� C����������� ���2�(��� AEF���C�������>� �� 6 ��� !����%&7�������� ��������� 8���������L���� �J�EF8���������L���� ���-)����EF8���������L���� �.���EF8������ ��� ����8���DD
Wykorzystanie obiektów
Interfejsy
269
Rysunek 8.22. Zmienna obj jest typu object.Oznacza to, że może wskazywać na obiekt Catlub na obiekt Dog. Powyższy kod testuje zawartośćzmiennej obj przez sprawdzenie, czy obiekt objobsługuje interfejs IDog
��� !����"���C����� ���"�� �0N� EF8D
��� !����"+��C����� ���*����(�0N� EF8D
�����������6�"+��CD
�����.�������6�"���CD
�����0N� C��������$�������E��#������#F���C�������!�E��4 �� �0�"F������C���������"+���������E"+��F��#8����������� �������������*����(�0N� EF8������D���DD
Rozpoznawanie interfejsu
Przed użyciem obiektu poprzez interfejs wartosprawdzić, czy obiekt rzeczywiście obsługujeinterfejs. Oczywiście, jeżeli mamy dostępdo definicji klasy, możemy na nią spojrzeći przekonać się, czy klasa implementuje interfejs.Czasami jednak mamy do czynienia z danymitypu ��%���, dla których trzeba zweryfikować,czy obiekt, na który wskazuje zmienna, jestzgodny z interfejsem, którego chcemy użyć.Istnieją dwa sposoby sprawdzenia, czy obiektobsługuje interfejs.
Aby sprawdzić,czy obiekt obsługuje interfejs:
1. Wpisz ��"7��%"��"�#������+8, gdzie ��%jest zmienną wskazującą na obiekt, którychcesz sprawdzić, natomiast �#������+jest nazwą interfejsu, dla którego chceszprzeprowadzić test (rysunek 8.22).
lub
Wpisz �#������+"5��"6"��%"�� �#������+,gdzie �#������+ jest interfejsem, dla któregochcesz przeprowadzić test, 5�� jest dowolnązmienną służącą do przechowywaniaodwołania do obiektu, a ��% jest obiektem,który chcesz sprawdzić.
Rozpoznawanie in
terfe
jsu
Rozdział 8.
270
2. Wpisz instrukcję ��"75��96����8. Jeżelipo wykonaniu pierwszego kroku zmienna5�� jest równa null, obiekt nie obsługujeinterfejsu. Jeśli test zwróci wartość różnąod null, obiekt obsługuje interfejs, a zmienna5�� wskazuje na odwołanie do interfejsu(rysunek 8.23).
Wskazówki
� Podczas korzystania z pierwszegomechanizmu, po uzyskaniu informacji,że obiekt obsługuje interfejs, aby użyćobiektu poprzez interfejs, należy zadeklarowaćzmienną typu interfejsu, po czym dokonaćkonwersji obiektu na interfejs.
� W przypadku drugiego mechanizmurozpoznawania interfejsu, zarówno konwersjaobiektu, jak i rozpoznanie następujew jednym kroku. Jeżeli obiekt obsługujeinterfejs, zmienna 5�� będzie wskazywaćna obiekt, w przeciwnym razie zmienna 5��przyjmie wartość null.
� Istnieje trzeci mechanizm rozpoznawania,czy obiekt obsługuje interfejs. Możnaspróbować dokonać konwersji obiektuna interfejs. Jeżeli obiekt nie obsługujeinterfejsu, konwersja spowoduje zgłoszeniewyjątku (błędu). Wyjątki zostaną omówionew rozdziale 11. „Obsługa błędów”.Wykorzystywanie wyjątków nie jestzalecane jako sposób rozpoznawaniaobsługi interfejsu przez obiekty, ponieważwyjątki mogą wpłynąć niekorzystniena wydajność działania programu.
Rysunek 8.23. Kiedy do sprawdzenia, czy obiektobsługuje interfejs, użyjemy polecenia as, uzyskamywynik null wtedy, gdy obiekt go nie obsługuje
��� !����"���C����� ���"�� �0N� EF8D
��� !����"+��C����� ���*����(�0N� EF8D
�����������6�"+��CD
�����.�������6�"���CD
�����0N� C��������$�������E��#������#F���C�������"+�����������4 �� �0�"7 �!�E����M���F����������� �������������*����(�0N� EF8���DD
Rozpoznawanie interfejsu
Interfejsy
271
Rysunek 8.24. Zwróć uwagę, że typem parametrumetody Communicate jest IHuman. Do metodymożna przekazać dowolny obiekt, który implementujeinterfejs. Każda z trzech klas implementuje interfejsw inny sposób. Metoda Communicate zwraca innyciąg znaków w zależności od przekazanego obiektu
��� !����"����C����� ���.���AEF8D
�����G��-�6�"'���C����������� ���.���AEF���C������ ��� � 2��4�������4��� 8���DD
�����.������6�"'���C����������� ���.���AEF���C������ ��� � �T-����S�A���U��N-�A������ X 8���DD
�����$ ����6�"'���C����������� ���.���AEF���C������ ��� � �T-��O�P�-V���Y-�T-U����� ���S����������S�T-X 8���DD
������� ��C����� �������������E������ �����F���C������ ��� ��� ���.���AEF8���D��������+��-*����EF���C�������� �����N� 8
������.�������������� ������%&8��������N� �������������E��F8������$ ����! ������ I����%&8��������N� �������������E�F8������G��-��������� 1���%&8��������N� �������������E��F8���DD
Wykorzystanie interfejsówdo polimorfizmu
Polimorfizm to mechanizm polegający na tym,że dwie powiązane ze sobą klasy mają nieznacznieróżniące się implementacje tej samej metody.W przypadku wykorzystania interfejsów jakotypów, programista może zdefiniować funkcje,które akceptują jako parametry dowolne obiektyimplementujące interfejs. Następnie, w zależnościod obiektu przesłanego do funkcji, wykonywanyjest nieco inny kod.
Aby wykorzystać polimorfizm:
1. W dowolnej klasie zdefiniuj metodę,w której jeden z parametrów wejściowychjest typu interfejsu.
2. Wywołaj metody interfejsu.
3. Przekaż do metody dowolny obiektobsługujący interfejs (rysunek 8.24).
Wskazówka
� Przed przekazaniem obiektu do metodynależy się upewnić, czy obiekt rzeczywiścieobsługuje interfejs (więcej informacjina ten temat znalazło się w podrozdziale„Rozpoznawanie interfejsu”we wcześniejszej części tego rozdziału).
Wykorzy
stanie in
terfe
jsów
Rozdział 8.
272
Interfejs będący pochodnąinnego interfejsu
Jeżeli inni programiści wykorzystują naszobiekt poprzez określony interfejs, a niezbędneokaże się ulepszenie interfejsu, wówczasnajlepiej pozostawić definicję oryginalnegointerfejsu bez zmian. W języku C# istniejemechanizm umożliwiający rozszerzanieinterfejsu bez dodawania metod do interfejsuoryginalnego. Działanie tego mechanizmupolega na tworzeniu interfejsów pochodnych.
Aby utworzyć interfejs będącypochodną innego interfejsu:
1. Zakładając, że wcześniej zdefiniowałeśjeden interfejs, zdefiniuj drugi.
2. Za nazwą interfejsu wpisz dwukropek,następnie $� �����������������, gdzie$� ����������������� jest nazwą interfejsu,który chcesz rozszerzyć.
3. Oba interfejsy: oryginalny i rozszerzonymożesz zaimplementować w ramachtej samej klasy (rysunek 8.25).
Rysunek 8.25. Interfejs IPresident stanowirozszerzenie interfejsu IParent. Oznacza to,że przy implementacji interfejsu IPresident należyzaimplementować nie tylko metody interfejsuIPresident, ale także metody interfejsu IParent
��� !����"�� ��C��������.��Z���(���-EF8D
��� !����"� �������6�"�� ��C��������+�������� �-EF8D
�����2�� ���6��*�������. AAimplementacja metod dla obu interfejsów
AAIparent oraz IPresident��������������.��Z���(���-EF���C���D
��������������+�������� �-EF���C���DD
Interfejs pochodną innego interfejsu
Interfejsy
273
Rysunek 8.26. Zaimplementowanie obu interfejsów:nadrzędnego i pochodnego jest tym samym,co zaimplementowanie tylko interfejsu pochodnego,ponieważ interfejs pochodny zawiera wszystkieskładowe interfejsu nadrzędnego
��� !����"�� ��C��������.��Z���(���-EF8D
��� !����"� �������6�"�� ��C��������+�������� �-EF8D
�����2�� ���6��*�������.���AAimplementacja metod dla obu interfejsów:
���AAIparent oraz IPresident��������������.��Z���(���-EF���C���D
��������������+�������� �-EF���C���DD
Rysunek 8.27. Mimo że klasa Telemarketerimplementuje zarówno interfejs IPerson, jakISendGifts, klasa ta nie jest zgodna z interfejsemIGivingPerson
��� !����"2������ ���6�"�� ��K".���2�!��CD
�����2 �����6��=�$��"*����CD�����(���� A��� �6��*����' ������=����CD
Wskazówki
� Definicje klas zaprezentowanychna rysunku 8.26 są sobie równoważne.Zaimplementowanie interfejsu oryginalnegoi pochodnego jest tym samym,co zaimplementowanie tylko interfejsupochodnego. W obu przypadkach uzyskujesię klasę zgodną z obydwoma interfejsami.
� Definicje klas przedstawionych na rysunku8.27 nie są sobie równoważne. Chociażinterfejs �0�5��+:����� jest kombinacjąinterfejsów: �:����� oraz �����0����,to zaimplementowanie interfejsu�0�5��+:����� nie jest tym samym,co oddzielne zaimplementowanie interfejsów�:����� i �����0����. Interfejs �0�5��+:�����może zawierać inne metody niż kombinacjametod interfejsów: �:����� oraz �����0����.
Interfe
js pochodną in
nego in
terfe
jsu
Rozdział 8.
274
Refaktoryzacja
Refaktoryzacja (ang. refactoring) to mechanizmwykorzystywany w programowaniu obiektowymdo działań z klasami i interfejsami. Polegaon na tym, że jeśli dwie klasy spełniającepodobne funkcje mają wspólny kod, wówczasze wspólnego kodu tworzy się klasę bazową,a następnie, na podstawie tej klasy bazowej,tworzy się podklasy. Podklasy zawierają tylkoten kod, który je od siebie odróżnia1.
Aby dokonać refaktoryzacji klasz wykorzystaniem interfejsów:
1. Jeżeli kilka klas implementuje tensam interfejs w podobny sposób(kod implementacyjny jest identycznydla wszystkich klas), utwórz klasę bazową.
2. Zaimplementuj interfejs w klasie bazowej.
3. Wprowadź w klasie bazowej kodimplementacyjny dla każdej metodyinterfejsu.
4. Utwórz klasy pochodne na podstawie klasybazowej.
5. Teraz możesz wykorzystać klasy pochodnepoprzez interfejs (rysunek 8.28).
Wskazówki
� Jeżeli klasa bazowa implementuje interfejs,klasy pochodne są także zgodne z interfejsem.
� W czasie projektowania klas, najpierwnależy zdefiniować interfejsy, późniejutworzyć klasę bazową implementującąte interfejsy, a następnie utworzyć podklasydziedziczące cechy klasy bazowej.Klasy pochodne wykorzystuje się poprzezinterfejs. Właśnie taki mechanizm częstowykorzystują doświadczeni programiścipodczas pisania aplikacji.
Rysunek 8.28. Obiektu Checking można użyćpoprzez interfejs IAccount, ponieważ klasaChecking jest pochodną klasy AccountImpl, a klasaAccountImpl implementuje interfejs IAccount.Innymi słowy, jeżeli dowolna klasa w hierarchiinadrzędnej implementuje interfejs, to klasapochodna także obsługuje ten interfejs
��� !����"������C��������)�A�+������E��������F8��������)�A������ �N�E��������F8D
����� -���������� � �-������C��������������)�A�+������E��������F���C���D
��������������)�A������ �N�E��������F���C���DD
���������A���6�-����������CD
�����.������6�-����������CD�����G�AC��������0��������EF���C������"���������������N�����A��EF8�����������)�A�+������E%77F8���DD
1 Z treści tego akapitu nie wynika, czym naprawdę jest refaktoryzacja. Jest to po prostu upraszczanie kodu,
czyli między innymi wydzielanie podklas — przyp. tłum.
Refaktoryzacja
Interfejsy
275
Rysunek 8.29. Klasa Dog implementuje interfejsIAnimal. Klasa GreatDane jest pochodną klasyDog, a zatem przejmuje implementację interfejsuIAnimal. Jednak co zrobić, aby zaimplementowaćmetodę Speak interfejsu IAnimal inaczej niżw implementacji Dog, a implementację metodyEat pozostawić bez zmian? W takiej sytuacji możnaponownie zaimplementować interfejs IAnimalw klasie GreatDane i zmienić implementacjęwybranych metod
��� !����"����C����� ���.���AEF8����� ������EF8D
�����+���6�"����C����� ���"�����.���AEF���C������ ��� � N��!M�N��!M 8���D
����� ���"��������EF���C������ ��� � [��M 8���DD
�����2 ���+���6�+���K��-�����C�������" �-�����+�����%&���C������ ��� � ���A���N��!M����A���N��!M 8���DD
Ponowna implementacjainterfejsów w klasie pochodnej
Czytelnicy, którzy przeczytali wcześniejszypodrozdział o refaktoryzacji, wiedzą o tym,że można utworzyć klasę bazową obsługującąinterfejs, a następnie napisać klasę pochodnądla tej klasy bazowej. Klasa pochodna równieżobsługuje interfejs. Czasami jednak trzebaprzesłonić jedną metodę lub kilka metodimplementacyjnych w klasie bazowej. W tymcelu można ponownie zaimplementowaćinterfejs w klasie pochodnej.
Aby ponownie zaimplementowaćinterfejs w klasie pochodnej:
1. Za nazwą klasy pochodnej wpisz dwukropek,a po nim nazwę interfejsu, który chceszzaimplementować ponownie.
2. Wprowadź implementację tylko dla tychmetod, które mają być różne od metod klasybazowej (rysunek 8.29).
Ponowna im
plementacja
interfe
jsów
Rozdział 8.
276
Wskazówka
� Innym sposobem ponownej implementacjimetody interfejsu jest zaznaczenie oryginalnejmetody implementacyjnej jako wirtualnej,a następnie przesłonięcie jej w podklasie(rysunek 8.30).
Rysunek 8.30. Ta metoda wymaga od autoraklasy bazowej zaznaczenia metody jako wirtualnej,co nie zawsze jest możliwe
��� !����"����C����� ���.���AEF8����� ������EF8D
�����+���6�"����C���������$�������� ���.���AEF���C������ ��� � N��!M�N��!M 8���D
����������� ������EF���C������ ��� � [��M 8���DD
�����2 ���+���6�+��C����������$������� ���.���AEF���C������ ��� � �00$M��00$M 8���DD
Ponowna implementacja interfejsów
Interfejsy
277
Rysunek 8.31. Środowisko ASP .NET przedrozpoczęciem aplikacji odczytuje ustawieniaw pliku web.config. Ustawienia w tym pliku możnawykorzystać w celu zarządzania sposobemuruchamiania aplikacji przez system ASP .NET
�����)�����&������������ +������� ����-��� ��� !����� �#���������������K������ !����� �#��� ,&�,����)�����&
Kończymy przykładowąaplikację
Pozostało jedynie kilka czynności, które trzebawykonać, aby nasza aplikacja stała się w pełnifunkcjonalna. W tym podrozdziale uzupełnimypozostały kod.
Najpierw upewnimy się, że środowiskoASP .NET wie o module użytkownika.
Aby uaktywnić moduł użytkownikaw aplikacji:
1. W module Solution Explorer kliknijdwukrotnie plik web.config.
2. Przewiń plik do końca i wpisz kod pokazanyna rysunku 8.31 zaraz za wierszem;<����� &���=.
Kończy
my przy
kładową aplik
ację
Rozdział 8.
278
To wszystko, co trzeba zrobić, aby uaktywnićmoduł użytkownika dla naszej aplikacji.Następny krok polega na wprowadzeniu koduna stronie dimensions.aspx, aby upewnić się,czy moduł działa.
Aby zakończyć stronę dimensions.aspx:
1. Dwukrotnie kliknij pozycję dimension.aspxw oknie Solution Explorer.
2. Dwukrotnie kliknij pusty obszarna formularzu, co spowoduje wywołanieedytora kodu. Kreator doda zdarzenie:�+�>���.
3. Wewnątrz metody :�+�>��� wprowadź kodzaprezentowany na rysunku 8.32. Kod tenspowoduje wyświetlenie wartości szerokościi wysokości w dwóch polach tekstowych(rysunek 8.33).
Wskazówki
� Aby przekonać się, że moduł działa, wystarczyzmienić rozmiar okna przeglądarki, a następniekliknąć przycisk Odśwież znajdujący się podpolami tekstowymi. W polach tekstowychpowinny pojawić się nowe rozmiary okna.
� Dzisiejszej nocy warto się dobrze wyspać.
Rysunek 8.32. W tym kodzie sprawdzana jestkolekcja Items i pobierane wartości __ClientWidthoraz __ClientHeight zapisane przez modułużytkownika
� ���������������/*���E��#�������� K.-���������� ����FC�����������+C��� 6 %%���&>������+�����F9GG>����������9H&+ �C�����"%&7 ������"��+C��� 6 %%���&>������+�����F9GG>��������"��9H&+ �C�����"%&7D
Rysunek 8.33. Aby przetestować moduł użytkownika,wystarczy zmienić rozmiary okna przeglądarki,a następnie kliknąć łącze Odśwież. Wartościszerokości i wysokości okna powinny ulec zmianie
Kończymy przykładową aplikację