Technika obiektowa

Klasy

Rzadko się zdarza, aby program wymagał tylko jednego obiektu, z jedną strukturą danych i ograniczoną liczbą metod. Częściej mamy do czynienia z zestawami obiektów, posługujących się wspólnymi danymi i metodami, ale różniącymi się zmiennymi stanu. Jeżeli dwa - lub więcej - obiektów korzystają z tych samych metod i zmiennych stanu, są członkami tej samej klasy obiektów. Obiekty można zaś uważać za instancje klasy. Na przykład wspomniany już adres zawiera strukturę adresową i metody operowania na niej. Natomiast adres konkretnej osoby będzie to instancja klasy adres.

Jak widać, rozróżnienie klasy i jego instancji jest łatwe: klasa to definicja tego, jakie dane można przechowywać w instancjach tej klasy i jak na nich operować, natomiast obiekt jest to ten element, który przechowuje dane i istnieje w programie.

Dziedziczenie

W aplikacjach często spotyka się bardzo podobne do siebie klasy obiektów. W banku można zdefiniować ogólną klasę konto, ale mogą też istnieć konta oszczędnościowe ROR, maklerskie, dewizowe lub lokata itp. Nie warto każdego z tych kont definiować oddzielnie jako klasy, gdyż definicję będą się zazębiały. Na pewno będą korzystać z tych samych zmiennych stanu (nazwisko, adres klienta, numer konta); będą także miały wspólne metody (wpłata, wypłata, udzielenie pełnomocnictwa, zamknięcie konta, obliczenie oprocentowania).

W oprogramowaniu obiektowym można usunąć tę nadmiarowość, definiując tylko raz klasę, która zawiera wszystkie wspomniane zmienne stanu i metody. Następnie tworzy się z niej specjalizowane klasy za pomocą dziedziczenia. Z głównej klasy (czasem zwanej superklasą) tworzy się subklasy. Aby utworzyć subklasę, należy do definicji klasy dodać specjalistyczne metody odróżniające ją od klasy macierzystej.

W skomplikowanej aplikacji może istnieć wiele klas i poziomów dziedziczenia między klasami, tworząc hierarchię dziedziczenia.

Polimorfizm

W językach proceduralnych każda zmienna może mieć tylko jedno znaczenie i wskazywać na tylko jeden typ danych. Podobnie, dwie funkcje w tym samym programie muszą różnić się nazwą.

W językach obiektowych wymagania te nie są przestrzegane. Dwie różne klasy mogą używać tej samej nazwy na oznaczenie różnych metod (tj. funkcji). Gdy wywoła się metodę za pomocą jej nazwy, system - na podstawie typu obiektu, na którym ma ona operować - określi, jaką metodę wywołać. To jest określane jako polimorfizm.

Prosty przykład polimorfizmu przytaczanego przy różnych okazjach omawiania technik obiektowych jest następujący. Do wykreślania figur geometrycznych na ekranie w językach proceduralnych używa się procedur o nazwie draw_tu_nazwa_figury() z odpowiednimi parametrami. Tak więc do wykreślenia trojkąta trzeba wywołać draw_trojkat(), zaś do wykreślenia okręgu draw_okrag(). Trzeba napisać tyle procedur, z właściwym nazwami, ile typów figur zamierza się wykreślać.

Można uniknąć problemów w programie napisanym w języku obiektowym. Należy najpierw stworzyć tyle klas, ile typów obiektów chce się wykreślać; każda klasa powinna zawierać metodę draw(). Następnie zamiast wywoływania procedur rysowania poszczególnych obiektów, wyśle się ten sam komunikat żądania narysowania figury do każdego obiektu, a sam obiekt wywoła procedurę rysowania, właściwą dla swoje klasy. Łatwo także dodaje się nowe typy figur, bez potrzeby modyfikowania głównego programu.

Programista może użyć tej samej nazwy metody wielokrotnie w pojedynczej klasie. Jeżeli trzeba obliczyć liczbę elementów z listy (liczbę nazwisk, pozycji menu, części samochodowych itp.), to nie można stworzyć oddzielnych procedur do liczenia każdego typu jej elementów, zwłaszcza że na ogół nie wiadomo, jakie to będą elementy. Musi więc istnieć metoda wyliczenia, niezależna od rodzaju zadanych parametrów; sama metoda musi umieć zastosować sposób wyliczania właściwy dla rodzaju elementów w liście. Ta technika wywoływania metod z różnymi parametrami nazywa się przeciążeniem metody (w prostszej wersji także przeciążeniem funkcji lub przeciążeniem operatora).


TOP 200