Programowanie obiektowe
Laboratorium z
Laboratorium z
przedmiotu Programowanie obiektowe
przedmiotu Programowanie obiektowe -
-zestaw 06
zestaw 06
Cel zajęć. Celem zajęć jest zaprojektowanie związków między klasami na podstawie słownego opisu
problemu i ich implementacja.
Wprowadzenie teoretyczne. Rozważana w ramach niniejszych zajęć tematyka jest ważna, gdyż
przed implementacją danej aplikacji należy zaprojektować jej strukturę w postaci diagramu klas. Aby ze zrozumieniem zrealizować zadania przewidziane do wykonania w ramach zajęć laboratoryjnych, należy znać znaczenie pojęć: zależności, asocjacji, agregacji, kompozycji.
1. Relacje zachodzące pomiędzy klasami
Zależność – jest najsłabszym rodzajem powiązania między klasami. Zależność pomiędzy klasami oznacza, że jedna klasa używa drugiej klasy lub posiada dotyczące niej informacje. Związek ten jest zazwyczaj krótkotrwały. Zależność występuje, kiedy zmiana specyfikacji jednej z klas może powodować konieczność wprowadzania zmian w innej klasie. Zależności używa się najczęściej do pokazania, że jedna klasa używa innej jako parametru jakiejś operacji.
Rys. 6 – Graficzna reprezentacja relacji zależności
Asocjacja – jest silniejszym typem powiązań niż zależność. Oznacza, że jeden obiekt jest związany z innym przez pewien okres czasu, jednak czas życia obiektów nie jest od siebie zależny (usunięcie jednego nie powoduje usunięcia drugiego).
Firma Pracownik Pracownicy 1 Pracodawca 1..* 3 Pracuje w
Rys. 7 – Graficzna reprezentacja relacji asocjacji
Asocjacja może zawierać nazwę, wraz z kierunkiem asocjacji, role (opcjonalne nazwy zadań klas w ramach zależności) oraz specyfikację liczebności (liczba obiektów z poszczególnych klas, mogących kojarzyć się z obiektami innej klasy).
Liczebność może być reprezentowana przez liczby całkowite lub przez przedziały: 0..1 – zero lub jeden obiekt
0..* - od zera do nieograniczonej liczby obiektów (często reprezentowane również w postaci „*”)
n ..* - od n do nieograniczonej liczby obiektów m..n – liczba obiektów z przedziału od m do n
Należy pamiętać, że za n i m można również podstawić liczby całkowite.
Agregacja – agregacja jest silniejszą formą asocjacji. Stanowi relację typu całość-część, w której część może należeć do kilku całości, a całość nie zarządza czasem istnienia części (usunięcie całości nie powoduje usunięcia części). Obiekt będący całością składa się z określonej liczby obiektów-składników.
Strona HTML Obrazy
Rys. 8 – Graficzna reprezentacja relacji asocjacji
Kompozycja (agregacja całkowita) – kompozycja jest najsilniejszym rodzajem powiązania między klasami. Stanowi relację całość-część, w której części są tworzone i zarządzane przez obiekt reprezentujący całość. „Część” może być zaangażowana tylko w jeden związek
Programowanie obiektowe
tego typu w danym czasie. Czasy życia instancji biorących udział w takim związku są ze sobą powiązane (usunięcie całości powoduje usunięcie części).
Strona HTML
head body
Rys. 9 – Graficzna reprezentacja relacji kompozycji
Zadanie 1.
Proszę zaprojektować diagram klas na podstawie słownego opisu problemu. Następnie proszę o implementację zaprojektowanego diagramu.
W trakcie implementacji proszę zbudować jedynie modele danych wraz zagnieżdżonymi kolekcjami. Proszę nie tworzyć metod typu Add, Remove, Get. Metody te w formie generycznych metod rozszerzających będą realizowane w zadaniu 2.
Więcej informacji na ten temat można znaleźć tutaj.
Opis problemu:
W pewnym ogrodzie zoologicznym znajdują się trzy rodzaje zwierząt: ssaki, ptaki i gady. O każdym ze zwierząt gromadzone są informacje na temat gatunku, rodzaju pożywienia oraz pochodzenia zwierzęcia. Każdy z trzech rodzajów zwierząt posiada też pewne unikatowe cechy i/lub umiejętności.
Ptaki potrafią latać, a informacja o maksymalnej długości lotu ptaka bez odpoczynku wyznaczana jest na podstawie iloczynu rozpiętości skrzydeł ptaka i jego wytrzymałość. Niektóre gady mogą być jadowite. W zoo gromadzone są także informacje na temat naturalnego środowiska życia ssaków.
Wszystkie zwierzęta trzymane są w klatkach, które mają pewną określoną pojemność. Klatka może wymagać posprzątania. Każda klatka jest identyfikowana za pomocą unikatowego numeru.
W zoo zatrudnieni są również opiekunowie, którzy odpowiadają m.in. za sprzątanie klatek. Każdy z nich może być przydzielony do opieki nad kilkoma klatkami.
Dyrekcja zoo potrzebuje na bieżąco sprawdzać informacje na temat wszystkich klatek wraz ze szczegółowymi informacjami na temat znajdujących się w nich zwierząt oraz na temat opiekunów pracujących w zoo.
Dyrekcja może podjąć decyzję o budowie nowej klatki, powiększeniu klatki, zatrudnieniu nowego pracownika oraz umieszczeniu w klatce nowego zwierzęcia.
Proszę o zaprojektowanie systemu umożliwiającego dyrekcji podjęcie powyższych działań.
Programowanie obiektowe
Zadanie 2.
Proszę do kodu z zadania 1 dodać implementację poniższego diagramu klas rozszerzającą funkcjonalność obecnego kodu o elementy generyczne umożliwiające dynamiczne zarządzanie kolekcjami.
Przedstawiony diagram klas proszę przetestować poniższym kodem testującym w kontekście modelu zaimplementowanego w zadaniu 1.
• klasy ActionExtensions oraz PrintActionExtensions są klasami statycznymi. Wszystkie metody tych klas są również statystyczne. Ich zadanie to dynamiczne rozszerzenie dowolnych obiektów o dodatkowe metody. Jest to obejście problemu dziedziczenia po jednej klasie w C#. W przypadku jeśli chcemy dostarczyć cześć funkcjonalności grupie klas które już dziedziczą np. po różnych obiektach wtedy możemy utworzyć taką klasę rozszerzającą.
• Aby metoda rozszerzyła dany typ obiektów należy go wskazać jako pierwszy argument metody poprzedzając go „this”. np. void Test(this IInfo obj){} metodę tą będzie można wywołać na każdym obiekcie dziczącym po IInfo.
var i = new Person(); i.Test();
• Dodatkowo w naszym zadaniu klasy rozszerzająca są generyczne. Metody generyczne przyjmują dowolne typy. np.
S Add<C,S>(this S container, C element) where S:IAction where C:IInfo
◦ metoda podłączy się pod dowolny typ S dziedziczący po IAction, a jako parametr przyjmie dowolny typ C dziedziczący po Iinfo.
◦ Wywołać można ją po prostu na obiekcie.
var d=new Dom(); i.Add(d);
◦ W przypadku metody:
C Get<C>(this IAction container, Fun<C,bool> fn = null)
Musimy dokładnie zdefiniować typ przy wywołaniu, gdyż nie przekazujemy żadnego obiektu z którego mogłaby odczytać typ w trakcie kompilacji.
i.Get<Dom>()
Musicie odpowiednio przypisać interfejsy IAction oraz IInfo waszym klasą z zadanie 1. 3
Programowanie obiektowe
Przykładowy main:Console.WriteLine("Nowe zoo"); var zoo = new Zoo();
zoo.Add(new Person("Romek", "Atomek", new DateTime(2000, 12, 01))) .Add(new Cage("Ptaszarnia", 10))
.Add(new Person("Wojtek", "Nowak", new DateTime(2002, 12, 01))) .Add(new Cage("Wybieg", 5))
.PrintInfo();
Console.WriteLine("Nowe zwierzęta:"); zoo.Get<Cage>(c => c.Id == "Wybieg")
.Add(new Bird("Gołąb", "Wiktor", "nasiona", "centrum miasta", 20)) .Add(new Bird("Gołąb", "Jacek", "nasiona", "centrum miasta", 20)) .PrintInfo();
Console.WriteLine("Klatki Romka:");
zoo.GetList<Cage>(c => c.Keeper != null && c.Keeper.FirstName == "Romek") .Print();
UWAGA!!!: Na następnych zajęciach odbędzie się kolokwium!!!
Podpowiedź
Poniżej przedstawiono przykładową (częściową) implementację powyższego diagramu klas.