Zagadnienia

2. Wstęp do programowania obiektowego

Wstęp do programowania obiektowego

2.1. Wstęp

  • Wszyscy o nim mówią, wszyscy go używają i nikt nie wie co to jest.

  • Podejście obiektowe swym znaczeniem wykracza daleko poza programowanie (ogólnie: opis skomplikowanych systemów).

  • Podejście obiektowe to inny sposób widzenia świata:

    • agenci do których wysyła się komunikaty,

    • zobowiązani do realizacji pewnych zadań,

    • realizujący je wg pewnych metod postępowania. Te metody są ukryte przed zlecającym wykonanie zadania.

  • Przykład: poczta

  • Programowanie obiektowe jest czymś więcej niż jedynie dodaniem do języka programowania kilku nowych cech, jest innym sposobem myślenia o procesie podziału problemów na podproblemy i tworzeniu programów.

  • Na programowanie obiektowe można patrzeć jako na symulowanie rozważanego świata.

  • W programowaniu obiektowym mamy do czynienia z zupełnie innym modelem obliczeń, zamiast komórek pamięci mamy obiekty (agentów), komunikaty i zobowiązania.

2.2. Pojęcia programowania obiektowego

  • Obiekt ma swój własny stan i swoje własne zachowanie (operacje).

  • Każdy obiekt jest egzemplarzem pewnej klasy.

  • Zachowanie obiektu jest określone w klasie tego obiektu.

  • Z każdym obiektem jest związany zbiór zobowiązań (responsibilities) - protokół.

  • Zachowanie obiektu można zaobserwować wysyłając do niego komunikat.

  • W odpowiedzi obiekt wykona swoją metodę, związaną z tym komunikatem.

  • To jakie akcje zostaną wykonane zależy od obiektu - obiekt innej klasy może wykonać w odpowiedzi na ten sam komunikat zupełnie inne akcje (polimorfizm).

  • Przesłanie komunikatu jest podobne do wywołania procedury, istotna różnica między nimi polega na tym, że to jakie akcje zostaną wykonane po przesłaniu komunikatu zależy od tego, do kogo ten komunikat został wysłany.

  • Wiązanie nazwy komunikatu z realizującą go metodą odbywa się dopiero podczas wykonywania, a nie podczas kompilowania, programu (metody wirtualne, wczesne i późne wiązanie metod).

  • Programowanie obiektowe polega także na tym, że staramy się co tylko się da zrzucić na innych (na agentów), a nie staramy się wszystkiego robić samemu (nawyk z programowania imperatywnego). Umożliwia to ponowne wykorzystywanie (reuse) oprogramowania.

  • ”Ważnym pierwszym krokiem w ponownym wykorzystywaniu komponentów jest chęć spróbowania zrobienia tego.”

  • Programowanie obiektowe nie ma większej mocy wyrażania, ale ułatwia rozwiązywanie problemów w sposób właściwy dla tworzenia dużych systemów.

  • Programowanie obiektowe stanowi następny etap ewolucji mechanizmów abstrakcji w programowaniu:

    • procedury,

    • bloki (w sensie Smalltalka),

    • moduły,

    • ATD,

    • programowanie obiektowe.

  • W kontekście programowania obiektowego mówimy o projektowaniu sterowanym zobowiązaniami (RDD Responsibility-Driven Design). Przerzucanie zobowiązań na innych wiąże się z dawaniem im większej samodzielności, dzięki czemu komponenty oprogramowania stają się mniej od siebie zależne, co z kolei ułatwia ich ponowne wykorzystywanie.

  • Podsumowanie własności programowania obiektowego (Alan Kay, 1993):

    • Wszystko jest obiektem.

    • Obliczenie realizują obiekty przesyłając między sobą komunikaty.

    • Obiekt ma swoją pamięć zawierającą obiekty.

    • Każdy obiekt jest egzemplarzem klasy.

    • Klasa stanowi repozytorium zachowania obiektu.

    • Klasy są zorganizowane w hierarchię dziedziczenia.

2.3. Dziedziczenie

  • Jedna z fundamentalnych własności podejścia obiektowego.

  • Klasy obiektów można kojarzyć w hierarchie klas (prowadzi to do drzew lub DAGów dziedziczenia).

  • Dane i zachowanie związane z klasami z wyższych poziomów tej hierarchii są dostępne w klasach po nich dziedziczących (pośrednio lub bezpośrednio).

  • Mówimy o nadklasach (klasach bazowych) i podklasach (klasach pochodnych).

  • W czystej postaci dziedziczenie odzwierciedla relację is-a (jest czymś). Bardzo często ta relacja jest mylona z relacją has-a (ma coś) dotyczącą składania.

  • Czasami chcemy wyrazić w hierarchii klas wyjątki (pingwin), można to uzyskać dzięki przedefiniowywaniu (podmienianiu) metod (method overriding).

  • Zasada podstawialności: zawsze powinno być możliwe podstawienie obiektów podklas w miejsce obiektów nadklas.

  • Możliwe zastosowania dziedziczenia:

    • specjalizacja (Kwadrat < Prostokąt),

    • specyfikacja (klasy abstrakcyjne),

    • rozszerzanie (Kolorowe Okno < Czarno-białe Okno),

    • ograniczanie (tak nie należy projektować - tu można zastosować składanie, Kolejka < Lista).

2.4. Podsumowanie zalet i wad

  • Fakt, że w podejściu obiektowym każdy obiekt jest całkowicie odpowiedzialny za swoje zachowanie, powoduje że tworzone zgodnie z tym podejściem oprogramowanie w naturalny sposób jest podzielone na (w dużym stopniu) niezależne od siebie komponenty.

  • Jest to niezwykle ważna zaleta, gdyż takie komponenty można projektować, implementować, testować, modyfikować i opisywać niezależnie od reszty systemu.

  • Dzięki temu, że oprogramowanie obiektowe składa się z wielu (w dużym stopniu) niezależnych od siebie komponentów, łatwo jest te komponenty ponownie wykorzystywać (reusability).

  • Tworzenie oprogramowania w metaforze porozumiewających się między sobą agentów skłania do bardziej abstrakcyjnego myślenia o programie: w kategoriach agentów, ich zobowiązań i przesyłanych między nimi komunikatów, z pominięciem tego jak są realizowane obsługujące te komunikaty metody

  • Ukrywanie informacji. Użytkownika klasy interesuje tylko interfejs należących do niej obiektów (komunikaty i ich znaczenie), a nie zawartość tych obiektów (metody i dane). Ten mechanizm nazywamy kapsułkowaniem (lub hermetyzacją).

  • Dziedziczenie pozwala pogodzić ze sobą dwie sprzeczne tendencje w tworzeniu oprogramowania:

    • chcemy żeby stworzone systemy były zamknięte,

    • chcemy żeby stworzone systemy były otwarte.

  • Możliwość ponownego wykorzystywania (nie trzeba od nowa pisać odziedziczonych metod i deklaracji odziedziczonych zmiennych).

  • Ponowne wykorzystywanie zwiększa niezawodność (szybciej wykrywa się błędy w częściej używanych fragmentach programów).

  • Ponowne wykorzystywanie pozwala szybciej tworzyć nowe systemy (budować je z klocków).

  • Zgodność interfejsów (gdy wiele klas dziedziczy po wspólnym przodku).

  • Szybkość wykonywania (programowanie obiektowe zachęca do tworzenia uniwersalnych narzędzi, rzadko kiedy takie narzędzia są równie efektywne, co narzędzia stworzone do jednego, konkretnego zastosowania).

  • Rozmiar programów (programowanie obiektowe zachęca do korzystania z bibliotek gotowych komponentów, korzystanie z takich bibliotek może zwiększać rozmiar programów).

  • Narzut związany z przekazywaniem komunikatów (wiązanie komunikatu z metodą odbywa się dopiero podczas wykonywania programu).

  • Efekt jo-jo (nadużywanie dziedziczenia może uczynić czytanie programu bardzo żmudnym procesem).

  • Modyfikacje kodu w nadklasach mają wpływ na podklasy i vice-versa (wirtualność metod).

Treść automatycznie generowana z plików źródłowych LaTeXa za pomocą oprogramowania wykorzystującego LaTeXML.

Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego.

Projekt współfinansowany przez Ministerstwo Nauki i Szkolnictwa Wyższego i przez Uniwersytet Warszawski.