« poprzedni punkt  następny punkt »

2. Wprowadzenie do obiektowości

Języki obiektowe posługują się pojęciem obiektu i klasy.
Dokładne definicje tych pojęć poznamy później. Teraz zamiast rozmyślania nad abstrakcyjnymi sformułowaniami spróbujmy uruchomić wyobraźnię i intuicję, licząc się z tym (i nie przerażając się tym), że niektóry rzeczy zostaną w pełni wyjaśnione dopiero w toku dalszej nauki.

Cóż to jest "obiekt" ? Intuicyjnie czujemy, że to coś w rodzaju "przedmiotu", czegoś co można wyodrębnić, nazwać, określić jego właściwości.
Na przykład obiektami będą: rower, samochód, pies, człowiek.

Każdy z tych obiektów ma inne właściwości. Np. człowiek ma imię, jest w określonym wieku. Samochód ma kolor i może też np. być charakteryzowany mocą silnika czy liczbą drzwi. 
Dwa samochody mają ten sam zestaw właściwości (atrybutów) np. markę, kolor i moc silnika. I choć marki i kolory mogą być różne i różna może być moc silników - to w pewnym sensie samochody te są podobne (bo opisujemy je za pomocą takich samych cech). Powiemy, że obiekty-samochody są obiektami tej samej klasy.

A klasa stanowi opis takich cech grupy podobnych obiektów, które są dla nich niezmienne.

Zauważmy dalej, że obiekty mogą wykonywać jakieś czynności. Powiemy: udostępniają jakieś usługi. Inne obiekty mogą "poprosić" je o wykonanie tych usług.
Np. obiekt-kierowca może "zlecić" obiektowi-samochodowi. by ten ruszył lub zatrzymał się (poprzez włączenie silnika i naciśnięcie na pedał gazu lub za pomocą wciśniecia hamulca).

Powiemy, że do obiektów posyłane są komunikaty, żądające od nich wykonania określonych usług.

Obiekty nie mogą wykonywać dowolnych czynności (świadczyć dowolnych usług). Samochód może ruszyć lub stanąć, ale nie zacznie śpiewać.
Można powiedzieć, że to, jakie usługi udostępniają obiekty,  jakie komunikaty możemy do nich posyłąć, prosząc je o wykonanie jakichś czynności - również jest jakąś ich cechą.

Zatem klasa będzie opisywac nie tylko takie wspólne cechy grupy podobnych obiektów jak kolor, czy wiek, czy waga, ale również zestawy usług, które obiekty tej klasy mogą świadczyć. A więc i komunikaty, które do tych obiektów można posłać.

Rozumowanie powyższe stanowią abstrakcyjne odzwierciedlenie cech rzeczywistości.

Gdybyśmy mieli w języku programowania podobne pojęcia, to moglibyśmy ujmować projekt rozwiązania rzeczywistego problemu i jego oprogramowanie w języku adekwatnym do problemu.
I to zapewniają języki obiektowe. Jest to ich bardzo ważna cecha, znacznie ułatwiająca tworzenie oprogramowania.

Możemy mieć np. klasę urządzeń elektrycznych o następujących atrybutach: szerokość, wysokość, stan (włączone-wyłączone) oraz udostępniających usługi: włączania i wyłączania.
Tak jest w rzeczywistości. I tak samo możemy to zapisać w (na razie wyimaginowanym) języku obiektowym, w którym za pomocą definicji klasy opiszemy atrybuty urządzeń elektrycznych oraz zestaw usług, przez nie udostępnianych - mający odzwierciedlenie w komunikatach, które można posłać do tych obiektów. Ten ostatni  - w wielu językach obiektowych - nazywany jest zestawem metod klasy (metoda jest czymś bardzo podobnym do funkcji).

class ElDev {
  width, height; <-- atrybuty: szerokość, wysokość, stan
  isOn;
================= Interfejs komunikatów
  method on()
   isOn = true; <--- usługa on (włącz), inaczej: metoda o nazwie on

  method off()
   isOn = false; <--- usługa off (wyłacz),inaczej: metoda o nazwie on
}

Gdy mamy dwa obiekty - egzemplarze klasy urządzeń elektrycznych, oznaczane a i b, to możemy symulować w programie sekwencję działań: włączenie urządzenia a, właczenie urządzenia b, wyłączenie urządzenia a, za pomocą komunikatów posyłanych do obiektów (inaczej wywołania metod na rzecz obiektów), np. w Javie (czy C++):

a.on();  // komunikat: obiekcie a włącz się
b.on();  // obiekcie b włącz się
a.off(); // obiekcie a wyłącz się

Oprócz odzwierciedlenia w programie "języka problemu" abstrakcja obiektowa ma jeszcze jedną ważną przewagę nad ujęciami nieobiektowymi.

Mianowicie, zwykle atrybuty obiektu nie są bezpośrednio dostępne. W programie z obiektami "rozmawiamy" za pomocą komunikatów, obiekty same "wiedzą najlepiej" jak zmieniać swoje stany. Dzięki temu nie możemy nic nieopatrznie popsuć, co więcej nie możemy zażądać od obiektu usługi, której on nie udostępnia.

Dane (atrybuty) są (powinny być) ukryte i są traktowane jako nierozdzielna całość z usługami - metodami.

Nazywa się to hermetyzacją (enkapsulacją) i oznacza znaczne zwiększenie odporności programu na błędy.

Podejście obiektowe umożliwia ponowne wykorzystanie już gotowych klas przy tworzeniu klas nowych, co znacznie oszczędza pracę przy kodowaniu, a także chroni przed błędami.
Jest to również odzwierciedlenie rzeczywistych sytuacji.

Np. komputer jest niewątpliwie urządzeniem elektrycznym. Jest obiektem klasy ElDev. Ale komputery (oprócz okreslonych w klasie ElDev atrybutów: wysokość, szerokość, stan: włączony-wyłączony) mają jakieś swoje specyficzne, wyspecjalizowane cechy.
Stanowią więc podklasę klasy urządzeń elektrycznych.
Tak jest w rzeczywistości. A w programie możemy to odzwierciedlić za pomocą koncepcji dziedziczenia klas. Klasa dziedzicząca inną przejmuje jej właściwości i ew. dodaje własne, wyspecjalizowane. Dzięki temu w klasie dziedziczącej możemy skupić się na specyficznych cechach jej obiektów, wiedząc, że podstawowe atrybuty i funkcjonalność zostały już określone w klasie dziedziczonej.
Np. tworząc klasę Komputer, dziedziczącą klasę urządzeń elektrycznych nie musimy od nowa zapisywać wszelkich cech i operacji na urządzeniu elektrycznym (np. nie musimy oprogramowywać metod on() czy off()). Musimy tylko dodać cechy wyspecjalizowane np. dla komputera - usługę wykonania jakiegoś programu.

Oczywiście program będzie obiektem klasy Program, a w komunikacie do obiektu-komputera powinniśmy podać jako argument obiekt-program do wykonania.
Dziedziczenie klasy ElDev przez klasę Komputer i dostarczenie nowej usługi (metody) run możemy zapisać (jeszcze nie w w Javie) tak (słowo extends oznacza tu dziedziczenie):

class Komputer extends ElDev {
    method run(Program p)
       if (isOn()) wykonanie_programu_p;
}

a następnie użyć nowej klasy Komputer w programie:

Komputer a, b, c;
Program x, y, z;
...
a.on(); a.run(x); ... a.off();

Tyle wprowadzenia, o charakterze bardzo wstępnym i raczej intuicyjnym.
Chodziło w nim o to, by zrozumieć pewne ważne cechy podejścia obiektowago na poziomie ogólnym, nie wchodząc jeszcze w szczegóły składni Javy. Dokładnie cechy podejścia obiektowego będziemy omawiać przez całe dwa semestry.
Już za chwilę jednak zobaczymy - przy okazji aplikacji powitalnych w jaki sposób w Javie operuje się na obiektach.


« poprzedni punkt  następny punkt »