programowanie obiektowe 03, c c++, c#


Modyfikatory dostępu. Właściwości

Przegląd zagadnień

0x08 graphic

Tematem modułu są sposoby kontrolowania dostępu do składowych klasy: omówionych wcześniej zmiennych składowych oraz metod. Omówione zostaną charakterystyczne dla obiektowych języków programowania modyfikatory dostępu określające, czy wartość zmiennej składowej można pobierać i modyfikować spoza klasy, czy tylko z wnętrza tej klasy.

Następnie zaprezentowane zostaną właściwości, czyli składowe klasy, obsługiwane w kodzie jak zmienne, lecz posiadające metody do pobierania i przypisywania im wartości.

Zagadnienia będą ilustrowane przykładowym kodem w języku C#.

Ostatnim etapem jest samodzielne przećwiczenie poznanych technik w laboratorium.

Modyfikatory dostępu

0x08 graphic

W klasach, z jakimi mieliśmy do czynienia na dotychczasowych zajęciach przyjęliśmy, że po utworzeniu egzemplarza (instancji) danej klasy można swobodnie pobierać wartości zmiennych składowych oraz je modyfikować, można też wywoływać wszystkie metody wchodzące w skład klasy. Takie podejście stwarza niebezpieczeństwo przypisania zmiennym składowym nieprawidłowych wartości lub wywołania metod w nieodpowiednim momencie, co może prowadzić do niepoprawnej pracy programu.

Z tego powodu, jedną z cech obiektowych języków programowania jest kontrola dostępności składowych klasy za pomocą modyfikatorów dostępu.

Modyfikator dostępu to jedno ze słów: public, protected, private, umieszczane przed definicją zmiennej lub metody. Dotychczas mieliśmy do czynienia ze swobodnym dostępem: publicznym (public). Możemy jednak zastrzec, że dostęp do danej zmiennej lub metody będzie dozwolony tylko z kodu wewnątrz klasy: korzystamy wówczas z modyfikatora private.

Pośredni stopień dostępu zapewnia modyfikator protected (chroniony). Tak oznaczone składowe będą dostępne tylko wewnątrz klasy oraz w klasach dziedziczących - o których więcej na kolejnych zajęciach.

Zamykanie funkcjonalności klasy bez dostępu z zewnątrz nazywane jest hermetyzacją (ang. encapsulation).

Modyfikatory dostępu - przykład 1

0x08 graphic

Chcemy stworzyć klasę na potrzeby misji marsjańskiej. Na powierzchnię Czerwonej Planety wysyłamy prosty pojazd: łazik. Sterowanie pojazdem jest bardzo proste: możemy zwiększać i zmniejszać prędkość obracania się kółeczek pojazdu, przy czym określona jest ich maksymalna prędkość. Ze względu na ograniczenia techniczne nie możemy po prostu podać prędkości, z jaką życzymy sobie, aby kółeczka się obracały.

W powyższym kodzie widzimy kilka zmiennych składowych i metod wraz z modyfikatorami dostępu (wyróżnione kolorem niebieskim). Mamy maksymalną prędkość, dostępną tylko wewnątrz klasy. Maksymalna prędkość jest ustawiana w konstruktorze klasy.

Prywatna zmienna Predkosc może być zwiększana lub zmniejszana za pomocą dwóch metod publicznych: Przyspiesz() oraz Zwolnij(), przy czym przyspieszając nie możemy przekroczyć maksymalnej prędkości, a zwalniając - zmniejszyć prędkość poniżej zera.

Z prawej strony widzimy diagram klasy według notacji UML. Publiczne składowe są oznaczane znakiem plusa (+), natomiast składowe prywatne - minusem (-). Składowe chronione będziemy oznaczać krzyżykiem (#).

Modyfikatory dostępu - przykład 1

0x08 graphic

Zobaczmy, jak modyfikatory dostępu mogą chronić zawartość. Po utworzeniu instancji klasy Lazik za pomocą konstruktora (publicznego), możemy korzystać z metod oznaczonych jako publiczne.

Jednak próba dostępu do składowych oznaczonych jako prywatne zakończy się błędem. W powyższym przykładzie nie możemy ani przypisać ani pobrać wartości prywatnej zmiennej składowej.

Modyfikatory dostępu - przykład 2

0x08 graphic

W tym przykładzie budujemy klasę, która może być wykorzystana do reprezentowania dowolnego ciała fizycznego i określenia jego temperatury. Mogą to być na przykład skały badane przez naszego łazika.

Ponieważ mamy do czynienia z misją naukową, temperaturę zapiszemy w kelwinach, jednak chcielibyśmy z niej korzystać bardziej intuicyjnie, wyrażając ją w stopniach Celsjusza. (Aby przeliczyć temperaturę w skali Celsjusza na kelwiny, należy dodać do niej 273,15. Nie istnieją temperatury niższe niż 0 K)

W klasie Cialo definiujemy prywatną zmienną składową, w której będziemy przechowywać temperaturę wyrażoną w kelwinach. Do pobierania i ustawiania jej wartości służą metody publiczne setTempK() i getTempK(). Metoda ustawiająca wartość sprawdza, czy podano prawidłową (nieujemną) temperaturę.

Mamy również metody do pobierania i ustawiania temperatury w stopniach Celsjusza, wykonujące odpowiednie przeliczenia.

Z prawej strony widzimy notację UML-ową tej klasy.

Modyfikatory dostępu - przykład 2

0x08 graphic

Po utworzeniu instancji klasy Cialo, możemy przypisać mu temperaturę w preferowanej przez nas skali - korzystając z publicznych metod klasy. Możemy też wyświetlić temperaturę ciała w wybranej skali.

Próba przypisania wartości prywatnej zmiennej składowej kończy się błędem.

Motywacja wykorzystania właściwości

0x08 graphic

W dotychczasowej praktyce zobaczyliśmy, że bezpośrednie pobranie wartości zmiennej składowej klasy jest nieco prostsze niż korzystanie z metody pobierającej taką wartość. Podobnie, prościej można przypisać bezpośrednio wartość zmiennej składowej niż wywoływać metody, które ustawiają tę wartość. Wszystko to może być prawdą, o ile zmienna składowa ma dostęp publiczny.

Z drugiej strony zobaczyliśmy, że przypisywanie i pobieranie wartości zmiennych składowych za pomocą odpowiednich metod pozwala na weryfikację poprawności, przeprowadzanie przeliczeń i wykonanie innych operacji po wywołaniu tych metod.

Właściwości

0x08 graphic

Składowe klasy, które łączą wymienione przed chwilą zalety, to właściwości (setter/getter properties).

Właściwości umożliwiają zdefiniowanie dwóch metod: set - służącej do przypisania wartości, oraz get - do pobrania wartości. Właściwość jest przy tym obsługiwana tak samo jak zmienna składowa klasy - można bezpośrednio przypisywać jej wartość (wówczas wywołana zostanie metoda set) lub bezpośrednio pobrać wartość (wywoływana jest metoda get).

Argument przekazany metodzie set, czyli wartość, jaką chcemy przypisać właściwości, widoczna jest wewnątrz tej metody pod nazwą value.

Właściwości nie muszą mieć obu metod! Jeśli chcemy utworzyć właściwość zachowującą się jak zmienna tylko do odczytu, definiujemy tylko metodę get. Jeśli chcemy, aby właściwość mogła być wykorzystana tylko do przypisywania wartości, tworzymy tylko metodę set.

Właściwości - przykład

0x08 graphic

W tym przykładzie tworzymy klasę Cialo o tej samej funkcjonalności, co wcześniej w tej prezentacji, posługujemy się jednak właściwościami. Bez zmian została prywatna zmienna składowa Temp, lecz cztery metody do pobierania i ustawiania temperatury, w kelwinach i stopniach Celsjusza, zostały zastąpione dwiema właściwościami: TempK i TempC, z metodami do zapisu i odczytu (wyróżnione kolorem niebieskim).

Tak jak wcześniej sprawdzamy, czy podana temperatura jest prawidłowa oraz dokonujemy odpowiednich przeliczeń.

Zachowujemy kontrolę dostępu do składowych klasy: temperatura przechowywana jest w prywatnej zmiennej, natomiast właściwości są publiczne.

Po prawej stronie klasa Cialo opisana przy pomocy schematu UML.

Właściwości - przykład

0x08 graphic

Zobaczmy, jak możemy korzystać ze zdefiniowanych przed chwilą właściwości: aby ustawić temperaturę ciała, po prostu przypisujemy wartość właściwości - identycznie, jak przypisuje się wartość zmiennej składowej.

Również proste jest pobranie wartości właściwości - pobieramy ją identycznie, jak pobiera się wartość zmiennej składowej.

Podsumowanie

0x08 graphic

Do tej pory omówiliśmy na tych zajęciach sposób kontroli dostępu do składowych klasy - z wewnątrz lub z zewnątrz tej klasy. Zmienne składowe, metody oraz właściwości mogą być prywatne, chronione lub publiczne.

Właściwości to składowe klasy, które pozwalają na zdefiniowanie metod przypisania i pobrania ich wartości, przy czym przypisywanie i pobieranie odbywa się w sposób identyczny jak w przypadku zmiennych składowych.

Pytania sprawdzające

0x08 graphic

Pytania kontrolne dla studentów:

  1. Wymień modyfikatory dostępu i opisz ich działanie.

  2. Jakie cechy zmiennych składowych oraz metod łączą właściwości?

Laboratorium

0x08 graphic

Podczas tego ćwiczenia rozbudujemy klasę Lazik, wprowadzoną w pierwszej części tych zajęć. Zadanie polega na wzbogaceniu klasy o podane niżej funkcjonalności, przy wykorzystaniu poznanych technik:

  1. Chcemy wyposażyć łazik w obrotomierz pokazujący prędkość obracania się kółeczek pojazdu. Powinna być to składowa umożliwiająca wygodne otrzymanie wyniku, bez możliwości zmiany prędkości.

  2. Łazik powinien być wyposażony w hamulec awaryjny, który mógłby być uruchomiony tylko przez wewnętrzny układ bezpieczeństwa.

  3. W przyszłości przewidujemy budowę nowego modelu łazika ze wszystkimi możliwościami obecnego modelu. Należy więc umożliwić dostęp do niektórych składowych również dla nowej klasy, która odziedziczy funkcjonalność klasy Lazik.

  4. W obecnej postaci łazik ma niewielkie możliwości. Pożądana byłaby możliwość jazdy wstecz oraz skręcania.

  5. Do jazdy w trudnym terenie z pewnością przyda się skrzynia biegów. Biegów może być kilka i można je zmieniać tylko w określony sposób.

L

L



Wyszukiwarka