C++ i jego plany

Programowanie Obiektowo Orientowane, wkrótce po powstaniu, zostało uznane za sensację i rewolucję w programowaniu. Wszyscy programiści są zgodni, że technika Obiektowo Orientowana (OO) będzie dominować w latach 90.

Programowanie Obiektowo Orientowane, wkrótce po powstaniu, zostało uznane za sensację i rewolucję w programowaniu. Wszyscy programiści są zgodni, że technika Obiektowo Orientowana (OO) będzie dominować w latach 90.

Programowanie OO stało się terminem bardzo modnym - i en vogue. Przypomina to trochę karierę, jaką w czasach pierwszych badań Marii Curie odniosło słowo "radioaktywny". W Paryżu było ono tak popularne, że niektóre firmy kosmetyczne reklamowały swoje wyroby jako "radioaktywne".

Dlaczego określenie "obiektowo orientowany" stało się tak modne? Oto najprostsza odpowiedź: Dlatego, że tą techniką jest bardziej naturalne i przyjemniejsze, trudniej w nim popełnić błędy, a gotowe programy są łatwiejsze do modyfikacji.

Argument, iż jest naturalniejsze lub przyjemniejsze, jest bardzo ważny dla pojedynczego programisty, jednak nie może wytłumaczyć światowej kariery. Zadecydował fakt, że programowanie techniką OO jest po prostu tańsze.

Dlaczego C++?

Zanim zajmiemy się konkretami, pragnę podkreślić różnicę w terminologii. Technika OO to sposób pisania programów. Technikę tę można realizować za pomocą narzędzia, którym jest język programowania wyposażony w odpowiednie instrumentarium.

Wśród obiektowych języków programowania szczególne miejsce zajmuje C++. Powodem, dla którego C++ zrobił karierę nawet wśród amatorów jest to, że język ten pozwala na łagodne przejście z klasycznych technik programowania na technikę obiektowo orientowaną.

Ta cecha nazywana jest hybrydowością języka. W programie można stosować technikę OO w takim stopniu, w jakim się ją opanowało. Tak też się dzieje najczęściej; programiści zaczynając pracę z C++ wybierają sobie z niego najpierw tylko jakieś rodzynki, a potem nieśmiało oswajają się z coraz bardziej wyszukanymi elementami.

Inne języki programowania - przeważnie wymagające od razu wejścia na głęboką wodę i stosowania wyłącznie techniki obiektowo orientowanej - mają, moim zdaniem, mniejsze szanse na tak zawrotną popularność.

Obiekty i klasy

Czy nigdy nie irytowało Cię, że gdy masz napisać program, to musisz swój problem, dotyczący jakichś realnych obiektów (silników krokowych, pokoi hotelowych itd.), zamienić na luźne liczby i podprogramy [funkcje]?

Rozwiązywanie problemu polega wtedy na żonglowaniu liczbami, które w programie wcale nie są ze sobą powiązane, ani też nie są powiązane z funkcjami. To tylko my wiemy, że dotyczą one tego samego silnika krokowego, tej samej pralki automatycznej, czy tego samego rachunku bankowego.

Dzieje się tak dlatego, że jedynymi typami danych, jakie oferują nam zwykłe języki programowania, są liczby całkowite, liczby rzeczywiste i znaki alfanumeryczne. Przykładowo, w języku C++ zwane są one typami int, float, char. Tymczasem wystarczy rzucić okiem na świat wokół nas: jest w nim więcej bogactwa, niż te liczby i znaki. Są układy elektroniczne, stery kierunku samolotu, pompy wodne w pralkach automatycznych, itd.

Program, który piszemy, zawsze odnosi się jakoś do zjawisk w świecie realnym. Jeśli jest to program do księgowania - odzwierciedla obiekty i metodykę pracy księgowego. Są czeki, faktury, kasa, konta. Z kolei program, który służy do gry w "Chińczyka" - operuje takimi obiektami jak pionki, plansza i kostka do gry. W programie sterującym promem kosmicznym obiektami są poszczególne podzespoły, którymi trzeba w określony sposób sterować.

Posługując się tradycyjnymi metodami programowania musimy ten wycinek świata realnego zapisać jakoś w komputerze. Rozbija się więc wszystko na luźne liczby, na których później pracuje program. Programowanie wówczas polega na - mówiąc obrazowo - wydawaniu poleceń małpie, którą nauczono dodawać. Mówi się: "a teraz dodaj tę liczbę do tamtej i rezultat umieść tutaj". Aby w ten sposób sterować promem kosmicznym trzeba się bardzo natrudzić. Z "Chińczykiem" też nie byłoby łatwo.

Programowanie obiektowo orientowane opiera się na innej idei. Jeśli program zajmuje się jakimiś obiektami i zjawiskami ze świata rzeczywistego, to nie rozbijamy tego wszystkiego na luźne liczby. Budujemy model. W programie tworzymy modele rzeczywistych obiektów. Tak zbudowane obiekty wyposażane są nie tylko w dane, ale także w zachowanie.

C++ pozwala nam na zdefiniowanie własnego typu danej. Oprócz typów standardowych mamy jeszcze nasz własny typ, wymyślony na użytek danego programu. Ten typ, to nie tylko jedna lub kilka zebranych razem liczb. To także sposób ich zachowania jako całości.

Zdefiniowany typ może być "modelem" jakiegoś rzeczywistego obiektu. Rzeczywisty obiekt - np. pionek do gry - można w komputerze opisać zespołem liczb i zachowań.

Dla pionka te liczby to np. jego kolor, dane opisujące jego"zewnętrzność", a także liczby reprezentujące jego stan wewnętrzny, bieżąca pozycja pionka na planszy do gry.

Z kolei zachowania pionka to zbiór funkcji, które może dla nas wykonać. Może to być ruch w przód o zadaną liczbę pól, czy powrót do punktu wyjścia w wypadku zbicia przez inny pionek.

Luźne liczby i luźne funkcje, o których wiemy, że opisują w programie pionek, zbieramy razem i budujemy z nich pewną całość. Powstaje w komputerze nowy typ danej: pionek.

Typ - mówimy dlatego, że kreujemy nie jeden konkretny obiekt, ale raczej klasę obiektów. Czyli, że na razie raczej wymyśliliśmy pionek - jeszcze żaden konkretny egzemplarz (obiekt) takiego pionka nie istnieje.

Klasa to ścisły odpowiednik typu zmiennej.

Dla porównania: tak w języku C++ definiuje się typ int o nazwie długość

@B_PROGR = int długość;

a tak obiekt klasy pionek k:

@B_PROGR = pionek k ;

Obsesją języka C++ jest to, by posługiwanie się obiektem było równie proste, jak posługiwanie się zwykłą daną typu całkowitego. Analogię posunięto do tego stopnia, że można "nauczyć" komputer jak ma postępować, gdy zobaczy przy obiektach nowego typu znaki +, -, *, ź, itd. Dzięki temu zapis instrukcji z udziałem obiektów typu zdefiniowanego przez użytkownika wygląda tak samo prosto, jak operacje na zmiennych typu całkowitego.

Dziedziczenie

Języki programowania, w których możemy definiować klasy obiektów nazywane są "object based" - czyli "obiektowe" (bazujące na obiektach). Nie jest to jednak jeszcze technika Obiektowo Orientowana. Co ją wyróżnia?

Kłopot w tym, że różni ludzie definiują różne kryteria kiedy to technika obiektowa przechodzi w obiektowo orientowaną. Najbezpieczniej przyjąć zasadę, że technikę OO poznaje się po dziedziczeniu i polimorfiźmie. Przyjrzyjmy się im.

Dziedzicznie - to technika tworzenia nowych klas obiektów na podstawie klas już istniejących. Załóżmy, że zdefiniowaliśmy w naszym programie jakąś klasę obiektów, a okazuje się, że potrzebna nam inna klasa obiektów, bardzo do niej podobna. W tej sytuacji, zamiast ponownego definiowania danych i funkcji, warto dokonać operacji dziedziczenia. Polega to na tym, że mówimy: "Definiuj nową klasę obiektów, a klasa ta będzie prawie identyczna jak tamta, ale z pewnymi różnicami. Oto te różnice ..."

Nowa klasa (klasa pochodna) jest związana ze swoim przodkiem (klasą podstawową) - szczególnego rodzaju "związkiem krwi". Pokażmy to na przykładzie. Jeśli w naszym programie mieliśmy klasę "pojazd" i skorzystaliśmy z niej definiując klasę "samochód", to na obiekty klasy samochód możemy mówić: to jest samochód, ale także prawdziwe jest powiedzenie: to jest pojazd.

Jakie to ma konsekwencje? Jeśli jakaś część programu (np. funkcja) zwykła pracować dla klasy pojazd, to nadaje się ona również do pracy z klasą samochód, gdyż samochód to szczególny rodzaj pojazdu. W deklaracji klasy "samochód" jest wyraźnie napisane, że samochód jest rodzajem pojazdu.

Ten chwyt ma poważne konsekwencje praktyczne, ponieważ ilustruje relacje między obiektami w świecie realnym.

Polimorfizm

Polimorfizm polega na tym, że istniejący kod programu (w skompilowanej postaci binarnej!) jest zdolny wywołać nawet taką funkcję, która jeszcze nie została napisana i może powstać dopiero przy jakichś późniejszych modyfikacjach programu.

Poli-morphos to z greckiego "wielość form". Otóż istniejący program potrafi się sam zorientować z jakim typem obiektu przyszło mu w danej chwili pracować i poprawnie zareaguje na taką sytuację.

Ma to bardzo ważne znaczenie praktyczne. Załóżmy, że piszemy program, który pracuje na obiektach typów, powiązanych ze sobą związkami dziedziczenia. Mieliśmy pojazd, od niego pochodził samochód, a od niego może pochodzić wiele różnych typów samochodów, np. Jaguar, VW, Fiat 126, itd. Dziedziczenie może być "wielopokoleniowe".

Ponieważ każdy typ samochodu wymaga nieco odmiennego traktowania, dlatego w naszym programie często występują instrukcje rozróżniające typ konkretnego samochodu.

Załóżmy, że każdy z typów samochodu ma wspólne zachowanie - tankowanie paliwa. Niby to proste, ale każdy typ samochodu tankuje się nieco inaczej; bo gdzie indziej znajduje się otwór (wlew) zbiornika, inną też pojemność miewają zbiorniki.

Sprawa jest więc oczywista. Każdy typ samochodu powinien mieć swoją własną funkcję "tankowanie". Podobnie z innymi funkcjami wspólnymi dla wszystkich samochodów. Ponieważ jednak w wypadku każdego typu samochodu taka funkcja wygląda nieco inaczej, dlatego w wielu miejscach programu są takie fragmenty kodu:

Jeśli to Renault - to zrób tak: ...

Jeśli to Porsche - to zrób siak: ...

Jeśli Rolls-Royce - to zrób owak: ...

Takie fragmenty są rozsiane po całym programie. Wyobraź sobie, że program powstawał w większym zespole i pewnego dnia szef mówi Ci, że wprowadza się do programu nową markę samochodu - Ferrari. Trzeba teraz zaangażować wszystkich ludzi po to, by w swoich częściach odnaleźli wszystkie te liczne miejsca i dopisali linijkę:

Jeśli Ferrari to zrób tak: ...

Wyższość techniki obiektowo orientowanej polega na tym, że żadnych takich modyfikacji robić nie trzeba. Dzęki polimorfizmowi (wywoływaniu funkcji wirtualnych) istniejący już kod potrafi zareagować na nowe typy obiektów. To dlatego, że w programie obiektowo orientowanym nie ma wcale linijek typu:

Jeśli Renault to zrób...

wymieniających wszystkie samochody, na których program pracuje. Na ich miejscu jest tylko jedna linijka: Dla pokazanego ci SAMOCHODU (sam się zorientuj, jaki to typ) zrób przewidzianą dla niego funkcję.

W rezultacie zostanie wywołana funkcja właściwa danemu modelowi samochodu. Zwróć uwagę, że może zostać wywołana nawet taka funkcja, która nie istniała nawet w momencie kiedyśmy ten fragment programu kompilowali. Korzyści z takiego rozwiązania oblicza się w tysiącach dolarów.

Oszczędność OO

W latach siedemdziesiątych, gdy kwitło programowanie proceduralne, wymóg łatwej modyfikowalności programów nie był jeszcze tak istotny. Dziś programy stały się ogromnie rozbudowane i pracuje nad nimi wiele zespołów zajmujących się mniejszymi fragmentami programu. Technika obiektowo orientowana pozwala, by programiści pracujący w jednym

zespole nie musieli znać pracy kolegów z innego zespołu.

Najważniejsze jednak, że jakakolwiek późniejsza modyfikacja programu (nawet tak poważna jak wprowadzenie nowego typu danej) możliwa jest bez angażowania wszystkich zespołów. Mimo to, że programy pisane w "tamtych" grupach, będą posługiwały się nowym typem danej.

Można to objaśnić prostą analogią. Jeśli konstruktorzy samochodów wyprodukują nowy model samochodu, to nie wymaga to przebudowy dróg. Skoro ten typ samochodu jest nadal samochodem, to dotychczasowe drogi są dla niego równie dobre. Dobre są dla niego również parkingi czy myjnie samochodowe. Taki właśnie jest sens polimorfizmu. Gdyby tak nie było, to każdy nowy model samochodu wymagałby budowy sieci nowych, właściwych tylko jemu dróg. Każda marka samochodu jeździłaby po swoich drogach. To właśnie kosztowałoby miliony. Niestety taka właśnie jest sytuacja w klasycznym podejściu do programowania.

Programowanie obiektowo orientowane stało się faktem. Nie jest to już żaden eksperyment, żadna nowinka, o której niebawem się zapomni. Nie ma już sensu pytanie, czy warto przestawiać się na programowanie OO czy nie. Sens ma tylko pytanie, kiedy to zrobić. Oczywiście, jak najszybciej.

Jerzy Grębosz jest autorem znajdującego się właśnie w druku podręcznika pt.:"Symfonia C++, Programowanie w języku C++ orientowane obiektowo."