Programowanie obiektowe
1
L
L
a
a
b
b
o
o
r
r
a
a
t
t
o
o
r
r
i
i
u
u
m
m
z
z
p
p
r
r
z
z
e
e
d
d
m
m
i
i
o
o
t
t
u
u
P
P
r
r
o
o
g
g
r
r
a
a
m
m
o
o
w
w
a
a
n
n
i
i
e
e
o
o
b
b
i
i
e
e
k
k
t
t
o
o
w
w
e
e
-
-
z
z
e
e
s
s
t
t
a
a
w
w
0
0
2
2
Cel zajęć. Celem zajęć jest zapoznanie z praktycznymi aspektami projektowania oraz implementacji klas i obiektów
z wykorzystaniem dziedziczenia.
Wprowadzenie teoretyczne. Rozważana w ramach niniejszych zajęć tematyka jest ważna, gdyż dziedziczenie i
polimorfizm są mechanizmami wykorzystywanymi powszechnie w programowaniu obiektowym. Aby ze
zrozumieniem zrealizować zadania, przewidziane do wykonania w ramach zajęć laboratoryjnych, należy znać
znaczenie pojęć takich jak: dziedziczenie, klasa bazowa, klasa potomna, polimorfizm, metoda wirtualna, kolekcja
List<T> i jej podstawowa funkcjonalność. Należy również znać podstawy języka modelowania systemów
informatycznych UML.
1. Dziedziczenie
Dziedziczenie polega na tworzenie nowej klasy na podstawie klasy już istniejącej.
W języku C# dziedziczeniu podlegają: pola klasy, właściwości oraz metody. Podobnie jak w C++ elementy
klasy, które w klasie bazowej zostały oznaczone jako „public” lub „protected”, w klasie potomnej również
będą miały ten sam zakres widoczności, natomiast elementy oznaczone jako „private” lub „internal”
nie
podlegają dziedziczeniu.
Mechanizm dziedziczenia przedstawia poniższy przykład:
Przykład 1 – Dziedziczenie
Programowanie obiektowe
2
Proszę zwrócić szczególną uwagę na linię kodu numer 32, w której wywoływany jest konstruktor klasy
bazowej. W języku C# do wywołania konstruktora klasy bazowej wykorzystywane jest słowo kluczowe
„base”.
Klasa bazowa (na przykładzie 1 - „Budynek”) to klasa, po której dziedziczy inna klasa nazywana klasą
potomną (na przykładzie 1 - „BudynekMieszkalny”).
2. Polimorfizm
Pojęcie polimorfizmu odnosi się do klas, które współdzielą te same metody, ale implementują je w różny
sposób. W praktyce oznacza to, że klasa potomna dziedzicząca daną metodę z klasy bazowej, może
przypisać jej zupełnie inną funkcjonalność.
Mechanizm polimorfizmu przedstawia poniższy przykład:
Przykład 2 – Polimorfizm
Programowanie obiektowe
3
Proszę zwrócić uwagę na sposób działania metody „WypiszInfo”. W linii 60 zostaje wywołana metoda
klasy bazowej, natomiast w liniach 62, 64 zostaje wywołana metoda klasy potomnej.
Proszę zauważyć, że w linii 63 do zmiennej typu „Budynek” zostaje przypisany obiekt
„BudynekMieszkalny”, a w linii 64 zostaje wywołana metoda „WypiszInfo” z klasy potomnej. Zadziałał tu
mechanizm polimorfizmu.
Metody z klasy bazowej, które mogą zostać przesłonione przez metody o tej samej nazwie z klasy
potomnej, należy oznaczyć modyfikatorem „virtual” (linia 25 w przykładzie 2). Metody te są metodami
wirtualnymi.
Metody z klasy potomnej, które mają przesłonić metodę o tej samej z klasy bazowej, należy oznaczyć
modyfikatorem „override” (linia 49 w przykładzie 2).
3. Kolekcja List<T>
Kolekcje to pojęcia stosowane w odniesieniu do klas, które umożliwiają przechowywanie oraz efektywne
przetwarzanie obiektów danego typu. Jedną z największych zalet kolekcji jest możliwość dynamicznej
zmiany ich rozmiaru – liczba przechowywanych przez kolekcje elementów nie jest ograniczona w
momencie utworzenia danej kolekcji, tak jak ma to miejsce w przypadku tablicy.
Jednym z podstawowych typów kolekcji jest lista - List<T>. Proste operacje wykonywane na liście zostaną
przedstawione do celów niniejszego laboratorium. Szczegółowe omówienie możliwości listy i innych
kolekcji nastąpi na wykładzie.
Informacje dotyczące kolekcji List<T> niezbędne do wykonania zadania laboratoryjnego:
Klasa List<T> została zdefiniowana w przestrzeni nazw „System.Collections.Generic”.
Litera „T” oznacza typ obiektów przechowywanych przez listę.
Utworzenie obiektu listy odbywa się za pomocą konstrukcji:
List<T> nazwaListy = new List<T>( )
gdzie „T” stanowi nazwę typu przechowywanego obiektu.
Podstawowe metody i właściwości listy prezentuje poniższy przykład:
Programowanie obiektowe
4
Przykład 3 – Metody kolekcji List<T>
4. UML – dziedziczenie na diagramie klas
Dziedziczenie w języku UML oznaczane jest za pomocą strzałki z pustym grotem wskazującym na klasę
bazową.
Rys. 1 – Reprezentacja dziedziczenia języku UML
Programowanie obiektowe
5
Zadanie 1. Proszę zrealizować aplikację obiektową, która powinna odznaczać się następującymi cechami:
Aplikacja powinna zawierać klasy zaimplementowane zgodnie z zamieszczonym poniżej diagramem klas.
Metody „WypiszInfo” powinny wypisywać na konsoli informacje na temat wartości wszystkich pól obiektów.
Metoda „WypiszInfo” klasy „Osoba” powinna być wirtualna, metody „WypiszInfo” w klasach pochodnych
(„Student”, „Piłkarz”), powinny ją przesłaniać.
Metoda „StrzelGola” powinna zwiększać o 1 wartość pola „liczbaGoli”.
Aby zrealizować zadanie należy wykonać następujące kroki:
Proszę o implementację klasy bazowej „Osoba”, jej pól i metod. Proszę pamiętać o modyfikatorze „virtual”,
który powinna posiadać metoda „WypiszInfo”.
Proszę o implementację klasy pochodnej „Student”, jej pól i metod. Proszę pamiętać o modyfikatorze
„override”, który powinna posiadać metoda „WypiszInfo”.
Proszę o implementację klasy pochodnej „Pilkarz”, jej pól i metod. Proszę pamiętać o modyfikatorze
„override”, który powinna posiadać metoda „WypiszInfo”.
Proszę o przetestowanie poprawności wykonania zadania za pomocą kodu testowego:
Programowanie obiektowe
6
Przy ocenie zadania główny nacisk będzie kładziony na:
Prawidłową implementację dziedziczenia.
Prawidłowy dobór modyfikatorów dostępu.
Zadanie 2. Proszę zrealizować aplikację obiektową, która powinna odznaczać się następującymi cechami:
Aplikacja stanowi rozszerzenie aplikacji z zadania nr 1.
Aplikacja powinna zawierać klasy zaimplementowane zgodnie z zamieszczonym poniżej diagramem klas.
Obiekty klasy „Student” powinny przechowywać kolekcję obiektów klasy „Ocena” za pomocą listy.
Metoda „DodajOcene” ma dodawać ocenę do listy ocen studenta.
Metoda „WypiszOceny( )” ma wypisywać informacje o wszystkich ocenach studenta.
Metoda „WypiszOceny(string nazwaPrzedmiotu)” ma wypisywać informacje o ocenach studenta z
przedmiotu o podanej nazwie.
Metoda „UsunOcene” ma usuwać ocenę studenta o podanych parametrach.
Metoda „UsunOceny( )” ma usuwać wszystkie oceny studenta.
Metoda „UsunOceny(string nazwaPrzedmiotu)” ma usuwać wszystkie oceny studenta z przedmiotu o
podanej nazwie.
Metoda „WypiszInfo” z klasy „Student” ma wypisywać także informacje o wszystkich ocenach studenta.
Programowanie obiektowe
7
Aby zrealizować zadanie należy wykonać następujące kroki:
Proszę o implementację klasy „Ocena”, jej pól i metod.
Proszę o implementację w klasie „Student” następującego pola:
Następnie proszę o dołączenie do projektu przestrzeni nazw „System.Colections.Generic”, z której pochodzi
używana kolekcja typu „List<T>”, poprzez dopisanie na początku kodu instrukcji:
Proszę o implementację metody „DodajOcene” w klasie „Student”. Metoda ta ma tworzyć nowy obiekt typu
„Ocena” i dodawać go do listy ocen za pomocą metody „Add” obiektu typu „List<Ocena>”.
Proszę o implementację metody „WypiszOceny”, która ma wypisywać na konsoli wszystkie oceny studenta.
Metoda ta powinna być zaimplementowana przy użyciu pętli „foreach” lub pętli „for”.
W tym celu niezbędna będzie także implementacja odpowiednich właściwości w klasie „Ocena”.
Proszę o implementację metody „WypiszOceny (string nazwaPrzedmiotu)”, która ma wypisywać na konsoli
wszystkie oceny studenta z przedmiotu o podanej nazwie. Metoda ta powinna być zaimplementowana przy
użyciu pętli „foreach” lub pętli „for”.
Proszę o implementację metody „UsunOcene”, która ma usuwać z listy ocen oceny o podanych parametrach.
Do tego celu należy użyć pętli „for”:
Programowanie obiektowe
8
UWAGA!
W języku C# istnieje prostszy sposób realizacji usunięcia z kolekcji obiektów o podanych parametrach.
Sposób ten zostanie przedstawiony na jednym z kolejnych wykładów.
Proszę o implementację metody „UsunOceny”, która ma usuwać z listy ocen wszystkie oceny. Do tego celu
należy użyć metody „Clear” kolekcji typu „List<Ocena>”.
Proszę o implementację metody „UsunOceny (string nazwaPrzedmiotu)”, która ma usuwać z listy ocen oceny
z przedmiotu o podanej nazwie.
Proszę o modyfikację metody „WypiszInfo” z klasy „Student”. Ma ona wypisywać także listę wszystkich ocen
studenta.
Proszę o przetestowanie poprawności wykonania zadania za pomocą poniższego kodu, który ma zostać
dodany do kodu testowego z poprzedniego zadania:
Przy ocenie zadania główny nacisk będzie kładziony na:
Poprawną implementację metod.
Programowanie obiektowe
9
Prawidłowy dobór modyfikatorów dostępu.
Zadanie do domu. Proszę zrealizować aplikację obiektową, która powinna odznaczać się następującymi cechami:
Zadanie do domu jest rozszerzeniem zadania 1.
Ilustruje je poniższy diagram klas.
Proszę o utworzenie klas „PilkarzNozny” i „PilkarzReczny”, które dziedziczą po klasie „Pilkarz”.
Metoda „StrzelGola” w klasie „PilkarzReczny” ma wywoływać metodę „StrzelGola” z klasy bazowej, a
ponadto wypisywać na ekranie konsoli komunikat „Ręczny strzelił!”.
Metoda „StrzelGola” w klasie „PilkarzNozny” ma wywoływać metodę „StrzelGola” z klasy bazowej, a
ponadto wypisywać na ekranie konsoli komunikat „Nożny strzelił!”.
Uwagi:
Metoda „StrzelGola” w klasie „Pilkarz” powinna być wirtualna, a jej odpowiedniki w klasach potomnych
powinny ją przesłaniać.
Metody „StrzelGola” z klas potomnych powinny odwoływać się do swoich odpowiedników za pomocą słowa
kluczowego „base” poprzez konstrukcję: „base.<nazwa metody>”
Programowanie obiektowe
10
Zagadnienia, które należy uznać za przyswojone w trakcie zajęć. Po zajęciach będzie obowiązywać praktyczna
znajomość:
Pojęcia dziedziczenia i polimorfizmu.
Tworzenie metod wirtualnych i ich przesłanianie.
Wykonywanie prostych operacji na kolekcjach „List” z przestrzeni nazw „System.Collections.Generic”.
Przedstawienie dziedziczenia na diagramie klas.
Zagadnienia do powtórzenia na następne zajęcia. Przed kolejnymi zajęciami należy powtórzyć następujące
zagadnienia:
Klasy abstrakcyjne.
Interfejsy.
Wybrane aspekty dotyczące implementacji z wykorzystaniem języka Java. Rozważane w ramach niniejszych
zajęć aspekty mogą być implementowane w różnorodnych technologiach służących do realizacji aplikacji
obiektowych, m.in. języku JAVA. Zasadnicze różnice w korzystaniu z języków C# i JAVA w kontekście tematyki
niniejszego laboratorium są następujące:
W języku Java dziedziczenie odbywa się przy użyciu słowa kluczowego „extends”.
W języku Java odpowiednikiem słowa kluczowego „base” jest słowo „super”.
W języku Java wywołanie konstruktora klasy bazowej odbywa się w ciele konstruktora klasy potomnej.
W języku Java nie istnieje modyfikator „virtual”, każda metoda jest domyślnie wirtualna.
Z kolei analogie w korzystaniu z języka C# i JAVA w kontekście tematyki niniejszego laboratorium są następujące:
W języku Java również nie istnieje wielodziedziczenie klas.
Mechanizm dziedziczenia w języku Java odbywa się na takiej samej zasadzie, jak w języku C#.
Uwagi szczegółowe dotyczące implementacji w języku Java są następujące:
Poniższy przykład przedstawia implementację dziedziczenia w języku Java. Jest odpowiednikiem przykładu nr
1.
Programowanie obiektowe
11
Przykład 4 – dziedziczenie w języku Java
Poniższy przykład przedstawia mechanizm polimorfizmu w języku Java. Jest odpowiednikiem przykładu nr 2.
Przykład 5 – polimorfizm w języku Java
Programowanie obiektowe
12