Podstawowe cechy programowania obiektowego

Programowanie obiektowe składa się z kilku założeń. Najczęściej wyróżniane pojęcia opisujące cechy programowania obiektowego:

  • abstrakcja,

  • dziedziczenie,

  • polimorfizm,

  • hermetyzacja (enkapsulacja).

Abstrakcja

Aby model tworzony w programie mógł odzwierciedlać świat, w którym żyjemy, tworzymy byty abstrakcyjne. Nie zawsze są one doprecyzowane, ale definiują pewien ogół. Ogół ten później jest uszczegóławiany o konkretne własności. Dzięki temu w programie panuje hierarchiczność, która jest odzwierciedleniem zdefiniowanych klasyfikacji (np. biologicznej). Z zasadą abstrakcji powiązane jest pojęcie klasy abstrakcyjnej, która tak naprawdę nie może istnieć w programie, ale występuje jako baza dla innych klas. Abstrakcja to ograniczenie cech obiektu ze świata rzeczywistego do cech istotnych z punktu widzenia rozwiązywanego problemu. Abstrakcja ma za zadanie uprościć rozwiązanie problemu i zwiększyć jego ogólność.

Przykładem abstrakcji może być byt o nazwie kształt. Kształt można opisać takimi właściwościami jak to, czy jest wypełniony, jeżeli tak, to jakim kolorem, czy jest ciągły i wreszcie jaki kolor ma jego kontur. Konkretne określenie kształtu następuje w momencie jego uszczegółowienia. Wówczas może on stać się kwadratem, trapezem czy okręgiem – każdy z nich będzie miał do dyspozycji wskazane właściwości kształtu.

Dziedziczenie

Ta zasada wiąże się z hierarchicznością tworzonych klas. Rozszerzanie klas stanowi odwzorowanie różnych klasyfikacji, które wykształciły się wraz z dostrzeżeniem wspólnych cech danych grup (np. organizmów lub pierwiastków chemicznych). Model ten postanowiono wprowadzić również do programowania, gdyż umożliwia tworzenie struktur danych różniących się od siebie, ale mających również wiele cech wspólnych. Dziedziczenie wykształciło się zatem po to, aby rozszerzać klasy o podobnych własnościach – bez konieczności przepisywania ich.

Polimorfizm

Polimorfizm oznacza wielopostaciowość. Jest to cecha, która nie może występować bez dwóch poprzednich. Definiuje on wiele mechanizmów w językach programowania, które pozwalają na traktowanie obiektu danej klasy nie tylko jako jednego ściśle określonego typu, ale także jako jego typów bazowych. W efekcie możemy sterować wieloma różnymi podklasami tej samej klasy bazowej lub interfejsuinterfejsinterfejsu. Dobrym przykładem obrazującym zasadę polimorfizmu może być np. kierownica, która używana jest do sterowania różnymi pojazdami. Niezależnie od pojazdu (rower, samochód czy samolot) obrót kierownicy w lewo zawsze będzie oznaczał skręt w lewo. Implementacja sterowania będzie różna w zależności od budowy pojazdu (w samolocie to ruch lotek, w samochodzie i rowerze – skręt kół), zasada działania kierownicy jest taka sama.

Z pojęciem polimorfizmu oraz dziedziczenia powiązane jest również pojęcie metod wirtualnych, czyli takich, które mogą być nadpisywane w klasach pochodnych. Metody wirtualne to także te funkcje, w których może nastąpić odwołanie do klasy bazowej. Wówczas język programowania musi udostępnić konstrukcję, dzięki której możliwe jest wywołanie oryginalnej, nadpisanej metody, wewnątrz metody, która ją nadpisała.

Hermetyzacja

Hermetyzacja (enkapsulacja) danych to założenie, zgodnie z którym mamy możliwość ukrycia pewnych danych i funkcji obiektu przed metodami innych klas (czyli tymi, które nie są wewnętrznymi metodami danej klasy) lub funkcjami, które nie mają dostępu do prywatnych składników (tzn. tymi, które nie są funkcjami zaprzyjaźnionymi).

Dzięki temu mechanizmowi otrzymujemy obiekt, do którego ukrytych pól i metod mamy dostęp tylko poprzez udostępnione metody publiczne. Hermetyzacja ogranicza popełnianie błędów.

Dzięki enkapsulacji wykształciło się wiele wzorców projektowych, które sprawiają, że praca przy dużych aplikacjach jest ułatwiona. Hermetyzacja wprowadza do języków programowania modyfikatory dostępu. Wyróżniamy trzy podstawowe tryby:

  • prywatny – zmienna może być modyfikowana i odczytywana tylko w klasie, w której została zadeklarowana,

  • chroniony – zmienna może być modyfikowana i odczytywana w klasie, w której została zadeklarowana oraz w klasach pochodnych od klasy, w której została zadeklarowana,

  • publiczny – zmienna może być modyfikowana i odczytywana w dowolnym miejscu programu, w którym mamy dostęp do obiektu.

W wielu modelach projektowych przyjmuje się, że każda zmienna w klasie powinna być poprzedzona modyfikatorem prywatnym lub chronionym, a w celu jej odczytania lub zmodyfikowania powinny zostać utworzone specjalne funkcje zwane getterami oraz setterami. Użycie takich funkcji zapobiega przypadkowemu dostępowi do zmiennych, a jednocześnie wprowadza możliwość kontroli ich wartości.

Przykład

Przyjrzyj się przykładowemu pseudokodowi, który prezentuje wymienione założenia programowania obiektowego:

Linia 1. abstrakcyjna klasa Figura. Linia 2. publiczna metoda czysto wirtualna wypiszPole otwórz nawias okrągły zamknij nawias okrągły. Linia 4. klasa Punkt dwukropek Figura. Linia 5. publiczny double x. Linia 6. publiczny double y. Linia 8. metoda wypiszPole otwórz nawias okrągły zamknij nawias okrągły. Linia 9. wypisz 0. Linia 11. klasa Kwadrat dwukropek Figura. Linia 12. prywatny Punkt a. Linia 13. prywatny Punkt b. Linia 14. prywatny Punkt c. Linia 15. prywatny Punkt d. Linia 16. prywatny double bok. Linia 18. konstruktor Kwadrat otwórz nawias okrągły Punkt punktZaczepienia przecinek double długośćBoku zamknij nawias okrągły. Linia 19. bok znak równości długośćBoku. Linia 20. a znak równości punktZaczepienia. Linia 21. b kropka x znak równości punktZaczepienia kropka x plus długośćBoku. Linia 22. b kropka y znak równości punktZaczepienia kropka y. Linia 23. c kropka x znak równości punktZaczepienia kropka x plus długośćBoku. Linia 24. c kropka y znak równości punktZaczepienia kropka y plus długośćBoku. Linia 25. d kropka x znak równości punktZaczepienia kropka x. Linia 26. d kropka y znak równości punktZaczepienia kropka y plus długośćBoku. Linia 28. metoda wypiszPole otwórz nawias okrągły zamknij nawias okrągły. Linia 29. wypisz bok asterysk bok.

Zacznijmy od wyjaśnienia poszczególnych klas po kolei.

Jako pierwsza zdefiniowana jest klasa abstrakcyjna Figura. Definiuje ona interfejs figur geometrycznych. W tym wypadku każda figura powinna potrafić wypisać swoje pole. Każda klasa, która będzie dziedziczyć po klasie Figura, musi nadpisać metodę wypiszPole().

Następnie definiujemy klasę Punkt, w której występują dwie współrzędne poprzedzone publicznym modyfikatorem dostępu. Oznacza to, że możemy odczytać oraz zmodyfikować je w dowolnym momencie wykonywania programu. Nadpisujemy w tym miejscu także metodę wypiszPole(), ponieważ bez tego klasa Punkt byłaby niekompletna. Pole punktu geometrycznego jest równe zero, zatem wypisujemy w tym miejscu zero.

Najbardziej złożoną klasą w całym programie jest Kwadrat. Punkty, z których składa się kwadrat, ustawione są jako prywatne – możemy je odczytywać i modyfikować tylko w klasie Kwadrat. Z tego względu nie może obejść się bez utworzenia konstruktora. W omawianym przypadku do konstruktora podajemy punktZaczepienia, czyli pierwszy punkt, od którego budujemy kwadrat. Każdy następny punkt utworzony zostaje na podstawie przekazanej przez parametr zmiennej długośćBoku. Również w przypadku klasy Kwadrat nadpisujemy metodę wypiszPole() (patrz wiersz nr 28).

Słownik

interfejs
interfejs

w programowaniu obiektowym interfejs to klasa abstrakcyjna, która zawiera tylko i wyłącznie metody czysto wirtualne

wzorzec projektowy
wzorzec projektowy

definicja modelu tworzenia aplikacji, systemów, programów itp., która zawiera sprawdzone rozwiązania częstych problemów pojawiających się podczas pracy projektowej; ułatwia pracę zespołową nad projektami, a także rozbudowę kodu i utrzymanie zależności występującymi w projekcie