może
implementować egzemplarze , a klasy dziedziczące z mo-
gą deklarować i tworzyć egzemplarze zagnieżdżonej klasy .
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 klasy
mogą 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 jest
wyłącznie do użytku wewnętrznego. Oto przykład:
Korzystaj ze specyfikatora dostępu , gdy chcesz utworzyć klasę zawierającą detale
implementacyjne biblioteki klas lub jakiejś innej aplikacji, uniemożliwiając tym samym
dostę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ływane
poś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:
Rozdział 7. Tworzenie klas
239
Taka definicja funkcji spowoduje wystąpienie błędu, wyraz zostanie
podkreślony linią falistą, a w liście zadań pojawi się uwaga, że niewłaściwie
udostę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. Gdy
pojawi się wewnętrzny problem, którego rozwiązanie jest bardziej złożone i wymaga
mocy, 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 dla
uż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 dodawanie
skł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ędzie
najbardziej korzystne; to znaczy, gdzie będą mogły być najczęściej wykorzystywane lub
zapewnią 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ści
dostępu — mogą one być prywatne, chronione, publiczne i zaprzyjaźnione — w celu
uwolnienia konsumentów lub generalizatorów od konieczności poznawania wszystkich
składowych danej klasy lub struktury. Ograniczając liczbę składowych klasy, których
muszą się oni nauczyć — poprzez właśnie ukrycie informacji — tworzone klasy są ła-
twiejsze do wykorzystania.
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ęści
rozdział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 musi
być zaznajomiony.
Ostatnie ze specyfikatorów — oraz — używane są w tych
przypadkach, 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 powinni
mieć 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 że
muszą 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. Nowe
reguł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 nowym
zasię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ęgu
wszystkie 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. !"