Programowanie obiektowe – powtórzenie wiadomości

paradygmacie programowaniaparadygmat programowaniaparadygmacie programowania obiektowego wyróżniamy dwa ważne pojęcia: klasa i obiekt. Co one oznaczają?

Najłatwiej wytłumaczyć to na przykładzie. Załóżmy, że piszemy grę komputerową o walczących ze sobą zakonach rycerskich. Już na początku pojawia się zasadnicze pytanie: jak przedstawić postać rycerza w programie?

Nietrudno sobie wyobrazić, jak rycerz powinien wyglądać na ekranie. Znacznie trudniej odzwierciedlić to w kodzie programu. W programowaniu wykorzystujemy zmienne, tablice, funkcje, instrukcje warunkowe i wiele innych elementów. W jaki sposób z ich pomocą można stworzyć postać rycerza?

Niezbędne są klasy. Z technicznego punktu widzenia klasa to zbiór zmiennych oraz funkcji opisujących postać, jaką chcemy przenieść ze świata realnego do wirtualnego. Zmienne klasy nazywa się polami klasy, a funkcje – metodami klasy. Pola klasy służą do opisania cech danej postaci, zaś metody do opisania czynności, jakie może ona wykonać. Wróćmy zatem do omawianego przykładu.

Podstawowymi cechami  rycerza w grze, opisywanymi przez pola klasy lub wartości atrybutów klasy, mogą być:

  • imię,

  • płeć,

  • siła,

  • szybkość,

  • wiek,

  • zdrowie.

Przykładowe czynności rycerza opisywane przez metody klasy to:

  • atak,

  • chodzenie,

  • bieg,

  • skok,

  • zażycie eliksiru.

Stwórzmy przykładową klasę rycerza w języku C++:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. class Rycerz prawy ukośnik asterysk nazwy klas zaczynamy wielką literą asterysk prawy ukośnik otwórz nawias klamrowy. Linia 6. public dwukropek prawy ukośnik prawy ukośnik znaczenia tej linii nie musisz jeszcze znać przecinek zostanie omówiona wkrótce. Linia 8. prawy ukośnik asterysk Pola klasy asterysk prawy ukośnik. Linia 10. string imie średnik prawy ukośnik prawy ukośnik imie ustawiamy jako ciąg znaków. Linia 11. string plec średnik. Linia 12. int wiek średnik prawy ukośnik prawy ukośnik wiek ustawiamy jako liczbę całkowitą. Linia 13. int sila średnik. Linia 14. int zdrowie średnik. Linia 16. prawy ukośnik asterysk Metody asterysk prawy ukośnik. Linia 18. void atak otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał atak cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 20. zamknij nawias klamrowy. Linia 22. void skok otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał skok cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void zazycieEliksiru otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz zażył eliksir cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy. Linia 29. zamknij nawias klamrowy średnik.
Ważne!

W języku C++ definicję klasy kończymy znakiem ;.

Klasa to tylko schemat opisujący, z czego ma składać się dana postać. Żadna z wymienionych cech nie ma przypisanej wartości, ponieważ żaden rycerz nie został jeszcze utworzony. Przypomnijmy, czym są obiekty.

Obiekty to konkretne reprezentacje danej klasy. Używając jednego schematu rycerza (klasy), możemy stworzyć dowolną liczbę rycerzy (obiektów).

Stwórzmy więc kilka obiektów klasy Rycerz:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. class Rycerz prawy ukośnik asterysk nazwy klas zaczynamy wielką literą asterysk prawy ukośnik otwórz nawias klamrowy. Linia 6. public dwukropek prawy ukośnik prawy ukośnik znaczenia tej linii nie musismy jeszcze znać przecinek zostanie omówiona wkrótce. Linia 8. prawy ukośnik asterysk Pola klasy asterysk prawy ukośnik. Linia 10. string imie średnik prawy ukośnik prawy ukośnik imie ustawiamy jako napis. Linia 11. string plec średnik. Linia 12. int wiek średnik prawy ukośnik prawy ukośnik wiek ustawiamy jako liczbę całkowitą. Linia 13. int sila średnik. Linia 14. int zdrowie średnik. Linia 16. prawy ukośnik asterysk Metody asterysk prawy ukośnik. Linia 18. void atak otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał atak cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 20. zamknij nawias klamrowy. Linia 22. void skok otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał skok cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void zazycieEliksiru otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz zażył eliksir cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy. Linia 29. zamknij nawias klamrowy średnik. Linia 31. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 32. Rycerz rycerz1 średnik prawy ukośnik prawy ukośnik pierwszy obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz1 apostrof. Linia 33. Rycerz rycerz2 średnik prawy ukośnik prawy ukośnik drugi obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz2 apostrof. Linia 34. Rycerz rycerz3 średnik prawy ukośnik prawy ukośnik trzeci obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz3 apostrof. Linia 36. return 0 średnik. Linia 37. zamknij nawias klamrowy.

Kilka obiektów już istnieje, ale żaden nie ma ustawionych wartości swoich cech. Każdemu polu publicznemu danego obiektu przypisujemy wartość z użyciem konstrukcji nazwaObiektu.nazwaPola. Przypiszmy tym obiektom poszczególne cechy.

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. class Rycerz prawy ukośnik asterysk nazwy klas zaczynamy wielką literą asterysk prawy ukośnik otwórz nawias klamrowy. Linia 6. public dwukropek prawy ukośnik prawy ukośnik znaczenia tej linii nie musimy jeszcze znać przecinek zostanie omówiona wkrótce. Linia 8. prawy ukośnik asterysk Pola klasy asterysk prawy ukośnik. Linia 10. string imie średnik prawy ukośnik prawy ukośnik imie ustawiamy jako napis. Linia 11. string plec średnik. Linia 12. int wiek średnik prawy ukośnik prawy ukośnik wiek ustawiamy jako liczbę całkowitą. Linia 13. int sila średnik. Linia 14. int zdrowie średnik. Linia 16. prawy ukośnik asterysk Metody asterysk prawy ukośnik. Linia 18. void atak otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał atak cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 20. zamknij nawias klamrowy. Linia 22. void skok otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 23. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał skok cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 24. zamknij nawias klamrowy. Linia 26. void zazycieEliksiru otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz zażył eliksir cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 28. zamknij nawias klamrowy. Linia 29. zamknij nawias klamrowy średnik. Linia 31. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 32. Rycerz rycerz1 średnik prawy ukośnik prawy ukośnik pierwszy obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz1 apostrof. Linia 33. Rycerz rycerz2 średnik prawy ukośnik prawy ukośnik drugi obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz2 apostrof. Linia 34. Rycerz rycerz3 średnik prawy ukośnik prawy ukośnik trzeci obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz3 apostrof. Linia 36. rycerz1 kropka imie znak równości cudzysłów Artur cudzysłów średnik prawy ukośnik prawy ukośnik przypisujemy wartość do pola apostrof imie apostrof obiektu apostrof rycerz1 apostrof. Linia 37. rycerz1 kropka plec znak równości cudzysłów mężczyzna cudzysłów średnik prawy ukośnik prawy ukośnik przypisujemy wartość do pola apostrof plec apostrof obiektu apostrof rycerz1 apostrof. Linia 38. rycerz1 kropka wiek znak równości 35 średnik prawy ukośnik prawy ukośnik przypisujemy wartość do pola apostrof wiek apostrof obiektu apostrof rycerz1 apostrof. Linia 39. rycerz1 kropka sila znak równości 150 średnik prawy ukośnik prawy ukośnik przypisujemy wartość do pola apostrof sila apostrof obiektu apostrof rycerz1 apostrof. Linia 40. rycerz1 kropka zdrowie znak równości 657 średnik prawy ukośnik prawy ukośnik przypisujemy wartość do pola apostrof zdrowie apostrof obiektu apostrof rycerz1 apostrof. Linia 42. return 0 średnik. Linia 43. zamknij nawias klamrowy.

Proces przypisywania wartości polom klasy można uprościć, korzystając z konstruktorów.

Rola konstruktora i destruktora

Konstruktor

Konstruktor to specjalna metoda pozwalająca na stworzenie obiektu danej klasy oraz ewentualne przypisanie do tego obiektu wartości pól danej klasy. Każda utworzona klasa posiada swój tak zwany konstruktor domyślny, który nie zawsze jest widoczny w definicji klasy. Nie przypisuje on żadnych wartości i służy wyłącznie do tworzenia obiektów danej klasy. W przedstawionym wcześniej kodzie, w linijkach 36, 37 oraz 38, został wykorzystany konstruktor domyślny.

Zasady budowy konstruktora:

  • konstruktor nie może mieć określonego typu zwracanego,

  • nazwa konstruktora jest taka sama jak nazwa klasy,

  • w nawiasach umieszczamy argumenty, których wartości zostaną przypisane do pól klasy,

  • klasa może zawierać kilka konstruktorów (muszą jednak różnić się liczbą argumentów lub typem argumentów),

  • utworzenie własnego konstruktora wymusza na nas jego stosowanie (konstruktor domyślny zostaje zastąpiony i niedostępny).

Stwórzmy konstruktor dla klasy Rycerz i użyjmy go do nadania wartości pól:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. class Rycerz prawy ukośnik asterysk nazwy klas zaczynamy wielką literą asterysk prawy ukośnik otwórz nawias klamrowy. Linia 6. public dwukropek prawy ukośnik prawy ukośnik znaczenia tej linii nie musimy jeszcze znać przecinek zostanie omówiona wkrótce. Linia 8. prawy ukośnik asterysk Pola klasy asterysk prawy ukośnik. Linia 10. string imie średnik prawy ukośnik prawy ukośnik imie ustawiamy jako napis. Linia 11. string plec średnik. Linia 12. int wiek średnik prawy ukośnik prawy ukośnik wiek ustawiamy jako liczbę całkowitą. Linia 13. int sila średnik. Linia 14. int zdrowie średnik. Linia 16. prawy ukośnik asterysk Konstruktor asterysk prawy ukośnik. Linia 18. Rycerz otwórz nawias okrągły string imie przecinek string plec przecinek int wiek przecinek int sila przecinek int zdrowie zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. this kropka imie znak równości imie średnik. Linia 20. this kropka plec znak równości plec średnik. Linia 21. this kropka wiek znak równości wiek średnik. Linia 22. this kropka sila znak równości sila średnik. Linia 23. this kropka zdrowie znak równości zdrowie średnik. Linia 24. zamknij nawias klamrowy. Linia 26. prawy ukośnik asterysk Metody asterysk prawy ukośnik. Linia 28. void atak otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 29. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał atak cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 30. zamknij nawias klamrowy. Linia 32. void skok otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 33. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał skok cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 34. zamknij nawias klamrowy. Linia 36. void zazycieEliksiru otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 37. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz zażył eliksir cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 38. zamknij nawias klamrowy. Linia 39. zamknij nawias klamrowy średnik. Linia 41. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 42. Rycerz rycerz1 otwórz nawias okrągły cudzysłów Artur cudzysłów przecinek cudzysłów mężczyzna cudzysłów przecinek 35 przecinek 150 przecinek 657 zamknij nawias okrągły średnik prawy ukośnik prawy ukośnik pierwszy obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz1 apostrof. Linia 43. Rycerz rycerz2 otwórz nawias okrągły cudzysłów Geralt cudzysłów przecinek cudzysłów mężczyzna cudzysłów przecinek 45 przecinek 450 przecinek 906 zamknij nawias okrągły średnik prawy ukośnik prawy ukośnik drugi obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz2 apostrof. Linia 44. Rycerz rycerz3 średnik prawy ukośnik prawy ukośnik utworzenie obiektu w ten sposób otwórz nawias okrągły z użyciem konstruktora domyślnego zamknij nawias okrągły nie powiedzie się. Linia 46. return 0 średnik. Linia 47. zamknij nawias klamrowy.

Jak widać, jest to sposób o wiele prostszy niż standardowe przypisywanie wartości. W konstruktorze dodatkowo użyliśmy operatora this, który pozwala odwoływać się bezpośrednio do pól danej klasy. Dzięki temu możemy wygodnie użyć takich samych nazw argumentów konstruktora.

Ważne!

W klasie może istnieć więcej niż jeden konstruktor (czyli możemy je przeciążać). Musi jednak spełniać przynajmniej jedno z dwóch wymagań: mieć inną liczbę argumentów albo inne typy argumentów od pozostałych konstruktorów. Dzięki temu program w sposób jednoznaczny wie, którego konstruktora należy użyć.

Destruktor

Destruktor to specjalna metoda wywoływana tuż przed usunięciem obiektu. Służy do wykonania wszystkich czynności, które składają się na jego „zniszczenie”, tak aby nie nastąpiły później w programie żadne nieprzewidziane błędy. Istnieje destruktor domyślny.

Zasady budowy destruktora:

  • destruktor nie może mieć określonego typu zwracanego,

  • nazwa destruktora składa się z nazwy klasy poprzedzonej znakiem ~,

  • destruktor nie może posiadać argumentów (w związku z czym klasa może mieć tylko jeden destruktor).

Stwórzmy przykładowy destruktor dla klasy Rycerz:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 3. using namespace std średnik. Linia 5. class Rycerz prawy ukośnik asterysk nazwy klas zaczynamy wielką literą asterysk prawy ukośnik otwórz nawias klamrowy. Linia 6. public dwukropek prawy ukośnik prawy ukośnik znaczenia tej linii nie musisz jeszcze znać przecinek zostanie omówiona wkrótce. Linia 8. prawy ukośnik asterysk Pola klasy asterysk prawy ukośnik. Linia 10. string imie średnik prawy ukośnik prawy ukośnik imie ustawiamy jako napis. Linia 11. string plec średnik. Linia 12. int wiek średnik prawy ukośnik prawy ukośnik wiek ustawiamy jako liczbę całkowitą. Linia 13. int sila średnik. Linia 14. int zdrowie średnik. Linia 16. prawy ukośnik asterysk Konstruktor asterysk prawy ukośnik. Linia 18. Rycerz otwórz nawias okrągły string konImie przecinek string konPlec przecinek int konWiek przecinek int konSila przecinek int konZdrowie zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. imie znak równości konImie średnik. Linia 20. plec znak równości konPlec średnik. Linia 21. wiek znak równości konWiek średnik. Linia 22. sila znak równości konSila średnik. Linia 23. zdrowie znak równości konZdrowie średnik. Linia 24. zamknij nawias klamrowy. Linia 26. prawy ukośnik asterysk Metody asterysk prawy ukośnik. Linia 28. void atak otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 29. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał atak cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 30. zamknij nawias klamrowy. Linia 32. void skok otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 33. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz wykonał skok cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 34. zamknij nawias klamrowy. Linia 36. void zazycieEliksiru otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 37. cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Rycerz zażył eliksir cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 38. zamknij nawias klamrowy. Linia 40. prawy ukośnik asterysk Destruktor asterysk prawy ukośnik. Linia 42. tylda Rycerz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 43. std dwukropek cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Nastąpiło zniszczenie obiektu cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny endl średnik. Linia 44. zamknij nawias klamrowy. Linia 45. zamknij nawias klamrowy średnik. Linia 47. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 48. Rycerz rycerz1 otwórz nawias okrągły cudzysłów Artur cudzysłów przecinek cudzysłów mężczyzna cudzysłów przecinek 35 przecinek 150 przecinek 657 zamknij nawias okrągły średnik prawy ukośnik prawy ukośnik pierwszy obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz1 apostrof. Linia 49. Rycerz rycerz2 otwórz nawias okrągły cudzysłów Geralt cudzysłów przecinek cudzysłów mężczyzna cudzysłów przecinek 45 przecinek 450 przecinek 906 zamknij nawias okrągły średnik prawy ukośnik prawy ukośnik drugi obiekt klasy apostrof Rycerz apostrof o nazwie apostrof rycerz2 apostrof. Linia 50. Rycerz rycerz3 średnik prawy ukośnik prawy ukośnik utworzenie obiektu w ten sposób otwórz nawias okrągły z użyciem konstruktora domyślnego zamknij nawias okrągły się nie powiedzie. Linia 52. return 0 średnik. Linia 53. zamknij nawias klamrowy.

W tym przypadku destruktor wykona się (nastąpi zniszczenie obiektu) automatycznie w momencie zakończenia pracy programu i to właśnie wtedy zostanie wypisany komunikat: „Nastąpiło zniszczenie obiektu”. Zastanów się, w jakich innych przypadkach mógłby wykonać się dekonstruktor.

Słownik

destruktor
destruktor

przeciwieństwo konstruktora; specjalna metoda, wywoływana przez program przed usunięciem obiektu

klasa
klasa

typ danych; szablon dla stworzenia obiektu

konstruktor
konstruktor

specjalna funkcja (metoda) danej klasy, wywoływana, gdy tworzona jest instancja danej klasy

paradygmat programowania
paradygmat programowania

wzorzec pisania oprogramowania, który definiuje, w jaki sposób programista postrzega sterowanie i wykonywanie programu komputerowego; przykłady paradygmatów to: programowanie obiektowe, programowanie funkcyjne, programowanie strukturalne oraz wiele innych