PO Wprowadzenie do programowania obiektowego

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania

Wprowadzenie

Na pierwszym wykładzie omówione zostało czym są i jak odnajdywać klasy pojęciowe. Przypomnijmy, że rozpoznanie klas pojęciowych pozwala lepiej zrozumieć dziedzinę problemu. Na tym wykładzie pokażemy, że myślenie obiektowe ułatwia tworzenie programów i wyjąśnimy co wyróżnia obiektowe języki programowania. Pokażemy również, że odnajdywanie klas pojęciowych nie było jedynie ćwiczeniem. Będzie się można na nich wzorować podczas projektowania i tworzenia programu, jednocześnie zmiejszając lukę reprezentacji.

Obiekty, a programowanie

Rozpoczęliśmy tworzenie modelu obiektowego i dzięki temu lepiej rozumiemy dziedzinę. Oczywiście nasz model nie jest od razu kompletny, ale warto się na nim wzorować podczas projektowania programu do gry w Monopol i tym samym ograniczyć lukę reprezentacji. Patrząc na diagramy ze stanem poszczególnych obiektów nie trudno o porównanie klas do rekordów, atrybutów do pól rekordów. To dobre skojarzenia. W językach obiektowych klasy rzeczywiście pełnią rolę typów danych, a obiekty są wartościami tych typów. Prawdziwą rewolucję podejście obiektowe wprowadza jednak dopiero w sposobie organizacji kodu operującego na tych danych. Jest on również zebrany w klasach. Czyli dane i kod na nich operujący są razem! Kod w każdej klasie jest podzielony na metody, które wywołuje się na rzecz jakiegoś egzemplarza. Metody mogą mieć parametry i zwracać jakieś wartości. Ponadto mają bezpośredni dostęp do danych egzemplarza na rzecz którego są wykonywane oraz mogą te dane modyfikować. Na poniższym diagramie widać klasę Kostka wraz z jej metodami wymienionymi w trzeciej przegródce. Metoda losujWartość() nie ma żadnych parametrów i nie zwraca żadnej wartości. Z jej nazwy można się domyślać, że powinna wylosować nową wartość atrybutu wskazywanaWartość. Metoda getWartość() : Integer również jest bezparametrowa, ale zwraca wartość będącą obiektem klasy Integer. Z jej nazwy można się domyślać, że zwraca wartość atrybutu wskazywanaWartość. Warto zwrócić uwagę, że dla tego atrybutu również określono, że przechowuje obiekt klasy Integer. Trzy kropki umieszczone w trzecie przegródce po ostatniej metodzie oznaczają, że klasa posiada jeszcze inne metody, ale ich nie pokazano.

Klasa programowa

Mimo, że na powyższym diagramie użyliśmy tej samej notacji, nie jest to już model dziedziny. Zaczęliśmy projektować oprogramowanie. Wiemy mniej więcej jakie informacje będą przechowywane w poszczególnych klasach. Trzeba określić typy ich atrybutów, zdecydować jak zrealizować powiązania oraz rozdzielić metody.

Po podjęciu tych decyzji i pokazaniu ich na diagramie nie mamy już do czynienia z klasami pojęciowymi, które przedstawiają rzeczywistość, ale z klasami projektowymi (ang. design class), które przedstawiają projekt oprogramowania. Można powiedzieć, że programowanie obiektowe polega na wyznaczaniu obiektom odpowiedzialności. Te odpowiedzialności są dwóch typów: za pamiętanie pewnych danych i za wykonywanie operacji na tych danych. Przy czym to zdecydowanie, które klasy wykonują jakie operacje jest trudniejsze i ważniejsze. Wszystkie szczegóły w jaki sposób obiekty wywiązują się z tych odpowiedzialności są ukryte w definicji klasy. Pozwala to łatwiej zapanować nad złożonością. Pisząc metody danej klasy można się skupić tylko na wycinku całego zadania – na realizacji odpowiedzialności wyznaczonych tej klasie. Jeżeli do wywiązania się z tych odpowiedzialności potrzeba wykonać operacje na danych innych obiektów, po prostu się im te operacje zleca. To tak samo jak w dobrze zorganizowanej firmie, która zatrudnia ekspertów z różnych dziedzin. Każdy obiekt odpowiada za swój kawałek i nie ingeruje w pracę pozostały.

Co z powiązaniami?

Ponieważ klasy projektowe mają być kiedyś zaimplementowane, nie wystarczy wiedza, że występują między nimi powiązania. Trzeba zdecydować jak te powiązania zrealizować. Zazwyczaj któraś z klas uczestniczących w powiązaniu będzie posiadała atrybut, na który zostanie przypisany obiekt drugiej klasy. Taki atrybut nazywa się referencją (ang. reference). Poniższy diagram pokazuje dwa równoważne sposoby pokazania, że klasa Gracz posiada referencję pionek, która wskazuje obiekt klasy Pionek

Sposoby przedstawiania referencji

W pierwszym wypadku referencja jest pokazana jako powiązanie. Atrybut będący referencją nie jest wymieniony w drugiej przegródce, tak jak zwykłe atrybuty. Jego nazwa jest umieszczona na powiązaniu przy klasie, która posiada referencję. Na drugim końcu powiązania znajduje się strzałka wskazująca widoczność. W tym wypadku to obiekty klasy Gracz mają referencję do obiektów klasy Pionek, a nie na odwrót. Referencje pokazuje się jako powiązanie, jeżeli obie klasy są warte uwagi. Jeżeli definicja klasy do której prowadzi referencja jest oczywista, bądź nieistotna z punktu widzenia tego co chcemy pokazać na tym diagramie, to referencję można pokazać jako zwykły atrybut i wskazać jego typ.

Zwróćmy uwagę, że również nazwa oraz stanKonta są referencjami. Klasy String i Integer są standardowo używane do przechowywania napisów oraz liczb całkowitych. Gotowe implementacje tych lub bardzo podobnie nazywających się klas wraz z wieloma przydatnymi metodami znajdują się w praktycznie wszystkich obiektowych językach programowania.

Typy podstawowe

W większości obiektowych języków programowania są również nieobiektowe typy danych. Nazywa się je typami podstawowymi lub prostymi (ang. basic types). Typy podstawowe służą do przechowywania pojedynczych znaków, liczb całkowitych i rzeczywistych różnej precyzji oraz wartości logicznych. Typy podstawowe są dodawane z dwóch powodów. Po pierwsze, ich wartości naturalnie nadają do używania się w wyrażeniach, a wypadku obiektów trzeba się posługiwać metodami. Po drugie, wartości typów podstawowych z założenia zajmują bardzo mało pamięci i operacje na nich mogą być realizowane bardzo efektywnie.