1.6.pdf

(758 KB) Pobierz
Od zera do gier kodera
6
OBIEKTY
Łyżka nie istnieje…
Neo w filmie „Matrix”
Lektura kilku ostatnich rozdziałów dała ci spore pojęcie o programowaniu w języku C++,
ze szczególnym uwzględnieniem sposób realizacji w nim pewnych algorytmów oraz
użycia takich konstrukcji jak pętle czy instrukcje warunkowe. Zapoznałeś się także z
możliwościami, jakie oferuje ten język w zakresie manipulowania bardziej złożonymi
porcjami informacji.
Wreszcie, miałeś sposobność realizacji konkretnej aplikacji - poczynając od jej
zaprojektowania, a na kodowaniu i ostatecznej kompilacji skończywszy. Wierzę, iż samo
programowanie było wtedy raczej zrozumiałe - chociaż nie pisaliśmy już wówczas
trywialnego kodu.
Podejrzewam jednak, że wstępne konstruowanie programu nosiło dla ciebie znamiona co
najmniej dziwnej czynności; wspominałem o tym zresztą w podsumowaniu całego
naszego projektu, obiecując pokazanie w niniejszym rozdziale znacznie przyjaźniejszej,
naturalniejszej i, jak sądzę, przyjemniejszej techniki programowania. Przyszedł czas, by
spełnić tę obietnicę.
Zatem nie tracąc czasu, zajmijmy się tym wyczekiwanym tęsknie zagadnieniem :)
Przedstawiamy klasy i obiekty
Poznamy teraz sposób kodowania znany jako programowanie obiektowe (ang. object-
oriented programming - OOP), które spełnia wszystkie niedawno złożone przeze mnie
obietnice. Nie dziwi więc, iż jest to najszerzej stosowana przez dzisiejszych programistów
technika projektowania i implementacji programów.
Nie zawsze jednak tak było; myślę zatem, że warto przyjrzeć się drodze, jaką pokonał
fach o nazwie programowanie komputerów - od początku aż do chwili obecnej. Dzięki
temu będziemy mogli lepiej docenić używane przez siebie narzędzia, z C++ na czele :)
Skrawek historii
Pomysł programowania komputerów jest nawet starszy niż one same. Zanim bowiem
powstały pierwsze maszyny zdolne do wykonywania sekwencji obliczeń, istniało już wiele
teoretycznych modeli, wedle których miałyby funkcjonować 64 .
Mało zachęcające początki
Nie dziwi więc, iż pojawienie się „mózgów elektronowych”, jak wtedy nazywano
komputery, na wielu uniwersytetach w latach 50. wywołało spory entuzjazm. Mnóstwo
64 Najbardziej znanym jest maszyna Turinga.
76934782.021.png
182
ludzi zaczęło zajmować się oprogramowywaniem tych wielkich i topornych urządzeń. Była
to praca na wskroś heroiczna - zważywszy, że „pisanie” programów oznaczało wtedy
odpowiednie dziurkowanie zwykłych papierowych kart i przepuszczanie je przez
wnętrzności maszyny. Najmniejszy błąd zmuszał do uruchamiania programu od początku,
co zazwyczaj skutkowało trafieniem na koniec kolejki oczekujących na możliwość
skorzystania z drogocennej mocy obliczeniowej.
Fotografia 1. ENIAC - pierwsza maszyna licząca nazwana komputerem, skonstruowana w
1946 roku. Był to doprawdy cud techniki - przy poborze mocy równym zaledwie 130 kW mógł
wykonać aż 5 tysięcy obliczeń na sekundę (ok. milion razy mniej niż współczesne komputery).
(zdjęcie pochodzi z serwisu Internetowe Muzeum Starych Programów i Komputerów )
Zwyczaj jej starannego wydzielania utrzymał się przez wiele lat, choć z czasem techniki
programistyczne uległy usprawnieniu. Kiedy koderzy (a właściwie hakerzy, bo w tych
czasach głównie maniacy zajmowali się komputerami) dostali wreszcie do dyspozycji
monitory i klawiatury (prymitywne i prawie w ogóle niepodobne do dzisiejszych cacek),
programowanie zaczęło bardziej przypominać znajomą nam czynność i stało się nieco
łatwiejsze. Jednakże określenie „przyjazne” było jeszcze zdecydowanie przedwczesne :)
Zakodowanie programu oznaczało najczęściej konieczność wklepywania długich rzędów
numerków, czyli jego kodu maszynowego . Dopiero później pojawiły się bardziej
zrozumiałe, lecz nadal niezbyt przyjazne języki asemblera , w których liczbowe
instrukcje procesora zastąpiono ich słownymi odpowiednikami. Cały czas było to jednak
operowanie na bardzo niskim poziomie abstrakcji , ściśle związanym ze sprzętem.
Listingi były więc mało czytelne i podobne np. do poniższego:
mov ah,4Ch
int 21h
Przyznasz chyba, że odgadnięcie działania tegoż kodu wymaga nielichych zdolności
profetycznych 65 ; )
Wyższy poziom
Nie dziwi więc, że kiedy tylko potencjał komputerów na to pozwolił (a stało się to na
początku lat 70.), powstały znacznie wygodniejsze w użyciu języki programowania
wysokiego poziomu (algorytmiczne), zwane też językami drugiej generacji .
Zawierały one, tak oczywiste dla nas, lecz wówczas nowatorskie, konstrukcje w rodzaju
instrukcji warunkowych czy pętli. Nie były też zależne od konkretnej platformy
sprzętowej, co czyniło programy w nich napisane wielce przenośnymi. Tak narodziło się
programowanie strukturalne.
W tym okresie stworzone zostały znane i używane do dziś języki - Pascal, C czy BASIC.
Programowanie stało się łatwiejsze, bardziej dostępne i popularniejsze - również wśród
65 Nie robi on jednak nic szczególnego, gdyż po prostu kończy działanie programu :) O dziwo, te dwie linijki
powinny funkcjonować na prawie wszystkich dzisiejszych pecetach z systemami DOS lub Windows!
76934782.022.png 76934782.023.png
 
183
niewielkiej jeszcze grupy użytkowników domowych komputerów. Pociągnęło to za sobą
także rozwój oprogramowania: pojawiły się systemy operacyjne w rodzaju Unixa, DOSa
czy Windows (wszystkie napisane w C), rosła też liczba przeznaczonych dlań aplikacji.
Chociaż niekiedy pisano jeszcze drobne fragmenty kodu w asemblerze, ogromna
większość projektów była już realizowana wedle zasad programowania strukturalnego.
Można w zasadzie powiedzieć, że z posiadanymi umiejętnościami sytuujemy się właśnie
w tym punkcie historii. Wprawdzie używamy języka C++, ale dotychczas korzystaliśmy
jedynie z tych jego możliwości, które były dostępne także w C.
To się oczywiście wkrótce zmieni :)
Skostniałe standardy
Czasy świetności metod programowania strukturalnego trwały zaskakująco długo, bo aż
kilkanaście lat. Może to się wydawać dziwne - szczególnie w odniesieniu do,
przywoływanego już niejednokrotnie, wyjątkowo sztucznego projektowania kodu przy
użyciu tychże metod. Jeżeli dodamy do tego fakt, iż już wtedy istniała całkiem pokaźna
liczba języków trzeciej generacji , pozwalających na programowanie obiektow e 66 ,
sytuacja jawi się wręcz niedorzecznie. Dlaczego koderzy nie porzucili swych wysłużonych
i topornych instrumentów przez tak długi okres?…
„Winowajcą” jest głównie język C, który zdążył przez ten czas urosnąć do rangi niemal
jedynego słusznego języka programowania. Jako że był on narzędziem, którego używano
nawet do pisania systemów operacyjnych, istniało mnóstwo jego kompilatorów oraz
ogromna liczba stworzonych w nim programów. Zmiana tak silnie zakorzenionego
standardu była w zasadzie niemożliwa, toteż przez wiele lat nikt się jej nie podjął.
Obiektów czar
Aż tu w 1983 roku duński programista Bjarne Stroustroup zaprezentował stworzony przez
siebie język C++. Miał on niezaprzeczalną zaletę (język, nie jego twórca ;D): łączył
składnię C (przez co zachowywał kompatybilność z istniejącymi aplikacjami) z
możliwościami programowania zorientowanego obiektowo.
Fakt ten sprawił, że C++ zaczął powoli wypierać swego poprzednika, zajmując czołowe
miejsce wśród używanych języków programowania. Zajmuje je zresztą do dziś.
Obiektowych następców dorobiły się też dwa pozostałe języki strukturalne. Pascal
wyewoluował w Object Pascala, który jest podstawą dla popularnego środowiska Delphi.
BASIC’iem natomiast zaopiekował się Microsoft, tworząc z niego Visual Basic; dopiero
jednak ostatnie wersje tego języka (oznaczone jako .NET) można nazwać w pełni
obiektowymi.
Co dalej?
Zaraz, w takim razie programowanie obiektowe i nasz ulubiony język C++ mają już z
górą dwadzieścia lat - w świecie komputerów to przecież cały eon! Czy zatem technologii
tej nie czeka rychły schyłek?…
Możnaby tak przypuszczać, gdyby istniała inna, równorzędna wobec OOPu technika
programowania. Dotychczas jednak nikt nie wynalazł niczego takiego i nie zanosi się na
to w przewidywalnej przyszłości :) Programowanie obiektowe ma się dzisiaj co najmniej
tak samo dobrze (a nawet znacznie lepiej), jak w chwili swego powstania i trudno sobie
nawet wyobrazić jego ewentualny zmierzch.
66 Były to na przykład LISP albo Smalltalk.
76934782.001.png 76934782.002.png 76934782.003.png 76934782.004.png 76934782.005.png 76934782.006.png 76934782.007.png 76934782.008.png
184
Naturalnie, zawsze można się z tym nie zgodzić :) Niektórzy przekonują nawet, iż istnieje
coś takiego jak języki czwartej generacji , zwane również deklaratywnymi. Zaliczają do
nich na przykład SQL (język zapytań do baz danych) czy XSL (transformacje XML).
Nie da się jednak ukryć faktu, że obszar zastosowań każdego z tych języków jest bardzo
specyficzny i ograniczony. Jeżeli bowiem kiedykolwiek będzie możliwe tworzenie
zwykłych aplikacji przy pomocy następców tychże języków, to lada dzień zbędni staną się
także sami programiści ;))
Pierwszy kontakt
Nadeszła wreszcie pora, kiedy poznamy podstawowe założenia osławionego
programowania obiektowego. Być może dowiemy się też, dlaczego jest takie wspaniałe ;)
Obiektowy świat
Z nazwy tej techniki programowania nietrudno wywnioskować, że jej najważniejszym
pojęciem jest obiekt . Tworząc obiekty i definiując ich nowe rodzaje można zbudować
dowolny program.
Wszystko jest obiektem
Ale czym w istocie jest taki obiekt? W języku potocznym słowo to może przecież oznaczać
w zasadzie wszystko. Obiektem można nazwać lampę stojącą na biurku, drzewo za
oknem, sąsiedni dom, samochód na ulicy, a nawet całe miasto. Jakkolwiek czasem będzie
to dość dziwny sposób nazewnictwa, ale jednak należy go uznać za całkowicie
dopuszczalny.
Rysunek 3, 4 i 5. Obiekty otaczają nas z każdej strony
Myśląc o programowaniu, znaczenie terminu ‘obiekt’ nie ulega zasadniczej zmianie. Także
tutaj obiektem może być praktycznie wszystko. Różnica polega jednak na tym, iż
programista występuje wówczas w roli stwórcy, pana i władcy wykreowanego „świata”.
Wprowadzając nowe obiekty i zapewniając współpracę między nimi, tworzy działający
system, podporządkowany realizacji określonego zadania.
Zanotujmy więc pierwsze spostrzeżenie:
Obiekt może reprezentować cokolwiek . Programista wykorzystuje obiekty jako cegiełki,
z których buduje gotowy program.
Określenie obiektu
Przed chwilą wykazaliśmy, że programowanie nie jest wcale tak oderwane od
rzeczywistości, jak się powszechnie sądzi :D Faktycznie techniki obiektowe powstały
właśnie dlatego, żeby przybliżyć nieco kodowanie do prawdziwego świata.
76934782.009.png 76934782.010.png 76934782.011.png 76934782.012.png 76934782.013.png 76934782.014.png 76934782.015.png 76934782.016.png 76934782.017.png 76934782.018.png
185
O ile jednak w odniesieniu do niego możemy swobodnie używać dość enigmatycznego
stwierdzenia, że „obiektem może być wszystko”, o tyle programowanie nie znosi przecież
żadnych nieścisłości. Obiekt musi więc dać się jasno zdefiniować i w jednoznaczny sposób
reprezentować w programie.
Wydawać by się mogło, iż to duże ograniczenie. Ale czy tak jest naprawdę?…
Wiele wskazuje na to, że nie. Pojęcie obiektu w rozumieniu programistycznym jest
bowiem na tyle elastyczne, że mieści w sobie niemal wszystko, co tylko można sobie
wymarzyć. Mianowicie:
Obiekt składa się z opisujących go danych oraz może wykonywać ustalone czynności .
Podobnie jak omówione niedawno struktury, obiekty zawierają pola , czyli zmienne. Ich
rolą jest przechowywanie pewnych informacji o obiekcie - jego charakterystyki.
Oczywiście, liczba i typy pól mogą być swobodnie definiowane przez programistę.
Oprócz tego obiekt może wykonywać na sobie pewne działania, a więc uruchamiać
zaprogramowane funkcje; nazywamy je metodami albo funkcjami składowymi .
Czynią one obiekt tworem aktywnym - nie jest on jedynie pojemnikiem na dane, lecz
może samodzielnie nimi manipulować.
Co to wszystko oznacza w praktyce? Najlepiej będzie, jeżeli prześledzimy to na
przykładzie.
Załóżmy, że chcemy mieć w programie obiekt jadącego samochodu (bo może piszemy
właśnie grę wyścigową?). Ustalamy więc dla niego pola, które będą go określały, oraz
metody, które będzie mógł wykonywać.
Polami mogą być widoczne cechy auta: jego marka czy kolor, a także te mniej rzucające
się w oczy, lecz pewnie ważne dla nas: długość, waga, aktualna prędkość i maksymalna
szybkość. Natomiast metodami uczynimy czynności, jakie nasz samochód mógłby
wykonywać: przyspieszenie, hamowanie albo skręt.
W ten oto prosty sposób stworzymy więc komputerową reprezentację samochodu. W
naszej grze moglibyśmy mieć wiele takich aut i nic nie stałoby na przeszkodzie, aby
każde miało np. inny kolor czy markę. Kiedy zaś dla jednego z nich wywołalibyśmy
metodę skrętu czy hamowania, zmieniłaby się prędkość tylko tego jednego samochodu
- zupełnie tak, jakby kierowca poruszył kierownicą lub wcisnął hamulec.
Schemat 16. Przykładowy obiekt samochodu
W idei obiektu widać zatem przeciwieństwo programowania strukturalnego. Tam
musieliśmy rozdzielać dane programu od jego kodu, co przy większych projektach
prowadziłoby do sporego bałaganu. W programowaniu obiektowym jest zgoła odwrotnie:
tworzymy niewielkie cząstki, będące połączeniem informacji oraz działania. Są one
niemal „namacalne”, dlatego łatwiej jest nam myśleć o nich o składnikach programu,
który budujemy.
Zapiszmy zatem drugie spostrzeżenie:
76934782.019.png 76934782.020.png
Zgłoś jeśli naruszono regulamin