Professional Documents
Culture Documents
PRZYKADOWY ROZDZIA
SPIS TRECI
KATALOG KSIEK
KATALOG ONLINE
ZAMW DRUKOWANY KATALOG
Zaawansowane
programowanie w PHP4
Autor: praca zbiorowa
ISBN: 83-7197-729-8
Tytu oryginau: Professional PHP 4
Format: B5, stron: 990
TWJ KOSZYK
DODAJ DO KOSZYKA
CENNIK I INFORMACJE
ZAMW INFORMACJE
O NOWOCIACH
ZAMW CENNIK
CZYTELNIA
FRAGMENTY KSIEK ONLINE
Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
W opinii autorw niniejsza ksika stanowi doskonae rdo wiedzy dla aktywnych
programistw, wykorzystujcych w swojej pracy PHP.
Ta ksika ma na celu umoliwienie twrcom aplikacji internetowych tworzenie
programw, ktre bd:
skalowalne,
wydajne,
bezpieczne,
modularne,
wielowarstwowe.
Ksika ta adresowana jest do programistw, ktrych znajomo PHP pozwala na
tworzenie i rozwijanie niewielkich aplikacji WWW. Pomimo e przedstawiamy skadni
PHP, liczymy na to, e programici czytajcy t ksik nie bd potrzebowali wykadu
na temat podstaw programowania.
Spis treci
O Autorach.....................................................................................................................................19
Wstp...........................................................................................................................................23
Dla kogo jest przeznaczona ta ksika? ................................................................................ 23
Zawarto ksiki .................................................................................................................. 24
Czego potrzeba, aby mona byo korzysta z tej ksiki? ...................................................... 27
Konwencje............................................................................................................................. 27
Rozdzia 2. Instalacja.....................................................................................................................35
Mamy ju PHP........................................................................................................................ 35
Przed instalacj ..................................................................................................................... 37
Decyzje instalacyjne .............................................................................................................. 38
Ktry system operacyjny? ................................................................................................ 38
Modu czy CGI? ................................................................................................................ 38
Ktry serwer WWW?......................................................................................................... 40
Instalacja MySQL, Apache i PHP............................................................................................ 40
Instalacja w systemie Windows ............................................................................................. 40
Instalacja bazy MySQL ..................................................................................................... 41
Jakie komplikacje mog wystpi?............................................................................. 42
Instalacja serwera Apache............................................................................................... 43
Jakie komplikacje mog wystpi?............................................................................. 46
Instalacja PHP ................................................................................................................. 46
Konfiguracja Apache do obsugi PHP................................................................................ 48
Jakie komplikacje mog wystpi?............................................................................. 49
Spis treci
htmspecialchars()....................................................................................................... 92
trim() .......................................................................................................................... 92
chr() oraz ord()............................................................................................................ 93
strlen()........................................................................................................................ 93
printf() oraz sprintf().................................................................................................... 93
Operacje liczbowe ............................................................................................................ 95
Operacje bitowe ......................................................................................................... 96
Operacje porwnania.................................................................................................. 97
Priorytety operatorw ................................................................................................. 98
Operacje logiczne............................................................................................................. 98
Priorytety operatorw ................................................................................................. 99
Tablice................................................................................................................................... 99
Zmienne zewntrzne.............................................................................................................. 99
Zmienne systemowe, zmienne GET oraz $HTTP_ Arrays .......................................... 100
Zmienne POST ......................................................................................................... 101
Cookies .................................................................................................................... 101
Zmienne CGI ............................................................................................................ 101
Zmienne nagwkw HTTP........................................................................................ 102
Spis treci
Spis treci
10
Spis treci
11
12
Spis treci
13
14
Spis treci
15
16
Spis treci
17
Skorowidz..................................................................................................................................953
126
Rozdzia 5.
127
a()
Model obiektowy
wywoanie
b()
wynik
wynik
wywoanie
c()
m
Obiekt 1
Obiekt 2
Obiekt 3
Obiekt 4
wyjcie
Wprowadzenie danych powoduje wywoanie funkcji , ktra wywouje funkcj .
Funkcja wywouje , ktra zwraca swj wynik do , ktra z kolei zwraca swj wynik funkcji . Funkcja ostatecznie generuje wynik programu. Funkcja w typowym
programie w nosiaby nazw . W modelu obiektowym obiekt wysya dania usug
do innych obiektw, co wida na przykadzie. Tutaj
wysya danie do
.
Z kolei
wysya danie do
i tak dalej, a do momentu, gdy
uzyska odpowied od
zawierajc wynik kocowy.
Ten mechanizm opiera si na udostpnianiu usug obiektom przez inne obiekty celem przekazywania informacji niezbdnej do ich pracy. Oznacza to moliwo podejmowania decyzji na podstawie informacji uzyskanych z innych obiektw. Przekazywanie komunikatw
stanowi samo w sobie przebieg programu. Dane i metody, a take sam kod implementujcy
obiekty, s zgromadzone w jednym centralnym miejscu.
Rnica pomidzy tymi dwoma sposobami polega na tym, e obiekty zawieraj cae dane
oraz mechanizmy dziaania, ktre powinny by ze sob zwizane, natomiast w rozwizaniu
proceduralnym dane i mechanizmy dziaania istniej niezalenie od siebie. Cecha ta pozwala
na atw analiz kodu wykorzystujcego technik obiektow i zwiksza modularno projektu.
Nie oznacza to jednak, e programy wykorzystujce rozwizanie proceduralne nie daj si
atwo rozwija. Wymaga to jednak znacznie wicej uwagi i organizacji ze strony programisty, aby zapewni odpowiednie umiejscowienie wszystkich elementw. Najlepsz rzecz
128
Rozdzia 5.
129
Klasy
Klasa jest definicj reprezentacji okrelonego typu danych. Klasy su jako sposb modelowania rnych typw danych w naszym systemie. Gdy chcemy utworzy obiekt, najpierw
uyjemy sowa kluczowego , aby zdefiniowa go, zanim uyjemy go w naszym skrypcie
w PHP. Rnica pomidzy klas a obiektem polega na tym, e klasa definiuje obiekty uywane
w programie. Zanim dowiemy si, w jaki sposb tworzy klasy, musimy zacz myle
o klasach jak o reprezentacji pojedynczej idei. W trakcie projektowania klasy trzeba stara
si, aby realizowaa konkretny cel w sposb jak najbardziej kompletny, nie wykraczajc
jednak poza przeznaczenie przypisane tej idei.
Klasa w PHP skada si z trzech gwnych elementw: atrybutw (reprezentujcych dane),
metod oraz konstruktorw. Atrybut stanowi porcj danych przechowywanych przez obiekt.
Obiekty mog zawiera dowoln liczb atrybutw na przykad jeli chcielibymy przedstawi samochd w postaci klasy, kierownica i skrzynia biegw byyby atrybutami klasy
. Metody okrelaj usugi, ktre obiekt udostpnia swoim klientom w celu manipulowania atrybutami. Przykadowo klasa moe udostpnia metody umoliwiajce wykonanie manewru skrtu pojazdem, wykorzystujc wewntrzny atrybut reprezentujcy kierownic.
Konstruktor jest specjaln metod inicjujc obiekt do stanu gotowoci. W PHP w kadej
klasie moe by zdefiniowany tylko jeden konstruktor. W klasie sensowne wydaje
si dodanie atrybutw
, , ,
,
i tym podobne.
Gdy klient zechce uy metod obiektu, konstruktor zapewnia, e kada z metod bdzie
dziaa na prawidowych atrybutach i zwrci oczekiwany wynik, na przykad aby mona
byo wczy radio w samochodzie, musi by ono zamontowane. W tym przypadku konstruktor jest odpowiedzialny za zamontowanie radia przed jego uyciem.
Oprcz realizowania funkcji inicjowania obiektu do stanu gotowoci, dodatkow rnic
midzy konstruktorami a metodami jest to, e konstruktory nie zwracaj jawnie adnych
wartoci. Kady konstruktor zwraca nowo zainicjowany obiekt, gotowy do uycia w programie. Dlatego uycie instrukcji
w definicji konstruktora jest nielegalne. W dalszej czci rozdziau zajmiemy si szerzej problematyk wykorzystania obiektw w programach.
Czsto spotykanym problemem jest konieczno opracowania prawidowego projektu
obiektw i konstruktorw. Jeli konstrukcja klasy zmusza programist do rcznego inicjowania atrybutw przed ich uyciem lub te zachowania okrelonej kolejnoci inicjowania
atrybutw, prowadzi to do powstania zagmatwanego i nieczytelnego kodu. Programowanie
zorientowane obiektowo pozwala unikn takich sytuacji. Jeli klasa zostanie zaprojektowana w sposb nie wykorzystujcy konstruktora do inicjacji kluczowych atrybutw, projekt taki uznajemy za nieprawidowy. Uwaaj, aby nie wpa w t puapk.
Dobrze zaprojektowana klasa moe nam zaoszczdzi wielu problemw w trakcie programowania, usuwania bdw i rozwijania projektu.
130
Jak wida, klasa jest po prostu zestawem definicji atrybutw (zmiennych) i metod (funkcji).
Atrybuty mog by zmiennymi typw prostych, takich jak liczby czy napisy, lub bardziej
zoonych, jak tablice czy inne obiekty. Poniewa PHP nie wymaga definicji typw, wystarczy po prostu wymieni nazwy atrybutw na pocztku definicji klasy, tak jak w powyszym przykadzie.
PHP umoliwia tworzenie nowych atrybutw w metodach w trakcie wykonania programu
i bd one dziaa prawidowo. Jest to jednak uwaane za zy nawyk programistyczny. Inni
programici powinni podczas analizy kodu pozna wszystkie atrybuty klasy na podstawie
definicji klasy bez koniecznoci zagbiania si w szczegy implementacji metod.
Metody stanowi wszelkie usugi udostpniane przez t klas jej klientom. Klientami mog
by inne programy, obiekty, skrypty itd.
Utwrzmy kod dla klasy . W tym przykadzie rozpoczynamy definicj klasy, uywajc sowa kluczowego . Za dobr praktyk programistyczn uwaa si rozpoczynanie
wszystkich nazw klas z wielkich liter, w celu odrnienia ich od nazw zmiennych i funkcji.
Programici przestrzegaj tej zasady od lat. Dziki temu atwo jest odrni konstruktor od
innych metod w klasie. Innym dobrym zwyczajem jest nazywanie plikw tak samo, jak
klasy, na przykad Samochod.php. Pojedynczy plik powinien zawiera definicj tylko jednej klasy. Jeli masz wiele klas odwoujcych si wzajemnie do siebie tworz kolekcj
klas, powiniene umieci je w katalogu gwnym swojej aplikacji. W przypadku duych
projektw taki zwyczaj staje si wymogiem.
Gdy projekt si rozronie, konieczne stanie si wykorzystanie struktury drzewiastej
w celu przechowywania klas wykorzystywanych w aplikacji. Bdziesz zmuszony do wykorzystania dyrektyw include_once() lub require_once(), aby wczy pliki definicji tych
klas do swoich skryptw.
Rozdzia 5.
131
W nieprawdopodobnie prostym modelu samochodu klasa skada si z silnika i stacyjki rozrusznika sucej do uruchomienia pojazdu. Prawdziwy samochd bdzie skada si z nadwozia,
drzwi, pedaw gazu, sprzga, hamulca, kierownicy, skrzyni biegw i wielu, wielu innych
elementw. W naszym przypadku chodzi jednak jedynie o demonstracj:
Nasz samochd rwnie posiada konstruktor inicjujcy silnik i stacyjk. Gdybymy nie
zainicjowali tych elementw, kade uycie metod lub zakoczyoby si
bdem. Jak wspomnielimy wczeniej, zadaniem konstruktora jest zainicjowanie wszystkich
elementw obiektu w celu zapewnienia, e wszystkie usugi bd mogy zosta wykorzystane wtedy, gdy bd potrzebne.
Aby odwoa si do atrybutu, naley uy konstrukcji ! przed nazw atrybutu. Jest to
rnica w porwnaniu z Jav i C++, gdzie takie odwoanie do obiektu klasy jest opcjonalne. PHP wymaga tego zapisu, poniewa jzyk ten nie jest dobrze wyposaony w obsug
zakresw widzialnoci zmiennych. W PHP istniej trzy poziomy przestrzeni nazw, w ktrych przechowywane s zmienne (przestrze nazw jest, oglnie rzecz biorc, kolekcj nazw
zmiennych).
Na najniszym poziomie wystpuje przestrze nazw uywana w celu przechowywania lokalnych zmiennych funkcji i metod. Kada zmienna definiowana na tym poziomie jest dodawana do lokalnej przestrzeni nazw. Kolejna przestrze nazw zawiera atrybuty obiektw.
Przestrze nazw najwyszego poziomu jest uywana do przechowywania zmiennych globalnych. Konstrukcja ! wskazuje, e odwoujemy si do zmiennej z przestrzeni nazw
obiektu (rodkowa warstwa). Jeli zapomnisz zastosowa zapis !, utworzysz zupenie now zmienn w lokalnej przestrzeni nazw. Poniewa bdzie ona odwoywa si do zupenie innej wartoci, mog powsta trudne do wychwycenia bdy logiczne.
Koniecznie uaktywnij opcj raportowania bdw, ktr omwimy w nastpnym rozdziale.
Dodatkowo dodaj kilka asercji, aby zabezpieczy si przed tym bdem, tak powszechnym przy pracy z klasami.
132
Metoda sprawdza, czy silnik dziaa, i jeli tak, zatrzymuje samochd. Zauwamy, e
sprawdzenie stanu uruchomienia samochodu mogoby zosta przeniesione do metody
obiektu silnika, co zwolnioby nas z koniecznoci obsugi tego przypadku. Projektujc klasy,
czsto napotkasz takie rozterki dotyczce umiejscowienia logiki obiektw. Podejmowanie
waciwych decyzji projektowych jest podstaw dobrego i skutecznego tworzenia aplikacji.
!
!
#
!
!
&
&
## (') *)+,
('
&
!
Obiekty
Obiekt w programie jest egzemplarzem klasy. Obiekty nazywamy egzemplarzami, poniewa mona utworzy wiele obiektw (czyli egzemplarzy) tej samej klasy tak jak na drodze moe by wiele samochodw tego samego typu. Aby utworzy dwa nowe samochody,
musimy wykona nastpujce dwa wiersze kodu:
-"#$
."#$
W celu utworzenia nowego egzemplarza klasy (to znaczy utworzenia obiektu) uywamy
sowa kluczowego
. Odwoania do nowo utworzonych obiektw zostaj umieszczone
w zmiennych oraz ". Mamy wic dwa obiekty samochodw, ktrych
moemy uy. Gdybymy chcieli utworzy dziesi samochodw, moglibymy uy tablicy
obiektw:
"
"/-/00
12"#$
&
Rozdzia 5.
133
Zauwa, e interfejs naszego obiektu jest atwy w uyciu. Nie musimy martwi si o to, jak
zosta zaimplementowany. Jako programista musisz tylko zna serwisy udostpniane przez
obiekt. Ten program mgby z powodzeniem sterowa procesem uruchamiania i zatrzymywania silnika prawdziwego samochodu. Szczegy kryjce si za metodami, a take atrybutami mog pozosta zupenie nieznane. Koncepcja tworzenia atwych w uyciu obiektw
doprowadza nas do tematu nastpnego podrozdziau, czyli hermetyzacji. Na razie zajmiemy
si jednak tworzeniem egzemplarzy obiektw z wykorzystaniem metod fabrycznych.
Metody fabryczne
Czasem wygodniej jest poprosi obiekt o utworzenie innego obiektu, zamiast samemu wywoywa konstruktor. Klasy udostpniajce takie usugi nazywamy klasami fabrycznymi,
a metody uywane do tworzenia obiektw nazywamy metodami fabrycznymi. Okrelenie
fabryczny wywodzi si ze skojarzenia z fabryk instytucj wytwarzajc gotowe wyroby.
Na przykad fabryk silnikw General Motors, produkujc silniki do samochodw, mona
porwna z obiektem fabrycznym tworzcym obiekty okrelonego typu. Nie zagbiajc si
w szczegy zaawansowanych technik obiektowych, zademonstrujemy teraz moliwe zastosowanie obiektw fabrycznych w tworzeniu aplikacji WWW. Mona je zastosowa do:
Dobrym zwyczajem programistycznym jest dodawanie przyrostka Factory na kocu nazwy klasy. Zachowanie tej konwencji, stosowanej powszechnie w rodowisku programistw wykorzystujcych techniki obiektowe, pozwoli innym programistom na pierwszy rzut
oka zidentyfikowa zadanie klasy:
134
Rozdzia 5.
135
Hermetyzacja (ang.Encapsulation)
Gdy zaywasz rodek przeciw blowi gowy, zwykle nie wiesz, z czego si skada. Jedyne,
co Ci interesuje, to jego dziaanie polegajce na usuniciu blu gowy. W podobny sposb
programici wykorzystuj obiekty. Gdy stosowalimy obiekt klasy , nie wiedzielimy niczego o jego skrzyni biegw, ukadzie wydechowym czy te silniku. Chcielimy tylko
przekrci kluczyk i uruchomi samochd. Umoliwienie takiego wykorzystania obiektu
powinno sta si gwnym celem jego projektanta.
Wszelkie skomplikowane dane i logik obiektu naley ukry wewntrz obiektu, udostpniajc jedynie wane usugi suce do posugiwania si obiektem. W ten sposb dokonujemy
hermetyzacji skomplikowanych danych i szczegw implementacyjnych wewntrz obiektu.
Jeli dokonamy tego waciwie, osigniemy dodatkowy zysk w postaci ukrycia informacji.
Jak wspomnielimy wczeniej, niewiadomo istnienia oraz rodzaju atrybutw danych
przechowywanych w strukturze klasy moe stanowi korzy dla wykorzystujcych j programistw.
Mimo e modyfikacja atrybutw obiektu jest poprawn operacj w PHP, jest to uznane
za zy nawyk programistyczny.
136
Gdy samochd zostanie uruchomiony, wystartuje z prdkoci 400 km/h. Moe to spowodowa wypadek i mier wielu uytkownikw ruchu drogowego. Oczywicie, nie chcemy
dopuci do wystpienia takiej sytuacji.
Skd samochd wie, jaki rodzaj kluczyka jest wymagany do jego uruchomienia? W tym
celu porwna nasz poprawnie skonstruowany kluczyk ze zmienn, ktra nie istnieje (co
w wyniku daje warto +) i w konsekwencji spowoduje, e samochd nie uruchomi silnika.
Taki bd nie zostanie wykryty przez interpreter, poniewa porwnujemy zmienn ,
nie kontrolujc przynalenoci do klasy. Dziwn sytuacj byoby zakupienie nowiutkiego
samochodu od dealera tylko w celu sprawdzenia, e kluczyk nie wsppracuje ze stacyjk.
Na kocu sprawdmy, co moe si sta, gdy przypiszemy warto + atrybutowi :
!
"/
!
Gdy wywoywana jest metoda , zostaje wywoany bd wykonania, poniewa atrybut
klasy nie jest obiektem klasy , gdy wymusilimy zmian wartoci
atrybutu na +. Jak wida, przypisywanie wartoci atrybutom bez porednictwa
metod klasy moe spowodowa wiele problemw. Gdy nad projektem pracuje wielu programistw, naley przewidzie sytuacj, w ktrej Twj kod bdzie czytany, a nawet uywany przez innych programistw.
Jaka nauka pynie z powyszego przykadu? Uywanie atrybutw obiektu bezporednio
moe mie nastpujce konsekwencje:
Dobr zasad jest takie zaprojektowanie klasy, aby udostpniaa usugi realizujce
wszelkie operacje na obiekcie. Naley unika bezporedniej modyfikacji atrybutw
obiektu z zewntrz i zawsze stosowa techniki hermetyzacji danych, aby wykorzysta
zalety ukrywania informacji. Niektre jzyki oferuj techniki blokowania dostpu do
atrybutw obiektw z zewntrz przez deklarowanie ich jako prywatne (private) lub chronione (protected). W obecnej implementacji PHP nie obsuguje adnej z tych technik,
ale na pewno pomocne okae si przestrzeganie ustalonych zasad programistycznych.
Rozdzia 5.
137
Dziedziczenie
Zapoznalimy si ju z podstawowymi elementami programowania zorientowanego obiektowo i z niektrymi jego dobrymi praktykami. Nadszed czas, aby zapozna si z mechanizmami udostpnianymi przez programowanie obiektowe, pozwalajcymi na podejmowanie
przejrzystych strategii rozwizywania skomplikowanych problemw.
Zamy, e naszym celem jest uporzdkowanie i zarzdzanie sklepem internetowym typu
amazon.com. Chcielibymy sprzedawa pyty CD, oprogramowanie, kasety VHS, pyty DVD
oraz ksiki. Korzystajc z tradycyjnych rozwiza opartych na funkcjach, moemy utworzy tradycyjn struktur do przechowywania informacji o tych mediach, na przykad:
Medium
id
nazwa
typ
wMagazynie
cena
ocena
Oczywicie, istnieje mnstwo rnic pomidzy ksikami, filmami, pytami CD i oprogramowaniem, wic zechcemy utworzy dodatkowe struktury przechowujce dane dla okrelonych typw medium:
PlytaCD
numerSeryjny
artysta
liczbaUtworow
nazwyUtworow
Oprogramowanie
numerSeryjny
wydawca
platforma
wymagania
Film
numerSeryjny
czasTrwania
reyser
obsada
typ
Ksiazka
ISBN
autor
liczbaStron
Aby napisa program wypisujcy elementy tablicy zawierajcej nasze media, zastosujemy
nastpujcy kod:
*
'$#D
.#
##
#
##"
'"
E"
#
## !"-
#
## !"4'4
#
## !'$"47 + $#$7F7@
#
5$4
#
## !$G+'#"HH
#
## !
#"@IIJ
#
## !
#"J
#
##12"#
##
' !*"-.@KJH@H@H@@H
' ! "4#9+#(4
' !
'* "J//
'1#
## !2"'
138
A jeli zechcemy doda jeszcze jeden typ medium? Musielibymy wrci do tego kodu,
doda jeszcze jedn instrukcj
i prawdopodobnie uaktualni w podobny sposb kod
w wielu innych miejscach naszej aplikacji. Programowanie zorientowane obiektowo udostpnia nam technik zwan dziedziczenie, ktra umoliwia umieszczenie szczegw specyficznych dla poszczeglnych typw obiektw w jednym miejscu, a take pozwala na
zgrupowanie cech wsplnych dla wszystkich typw obiektw. Wykorzystujc t technik,
moemy zupenie wykluczy instrukcj w przypadkach podobnych do rozpatrywanego przez nas.
W naszym przykadzie sklepu multimedialnego moemy wyodrbni podobiestwa pomidzy rodzajami mediw w jednej klasie obiektw. Klasa taka nosi nazw klasy macierzystej,
klasy podstawowej lub klasy nadrzdnej. W ten sposb utworzymy najbardziej abstrakcyjn implementacj (atrybuty i metody), ktra odnosi si do kadego elementu, jaki chcemy
umieci w naszym sklepie. Poniej przedstawiamy fikcyjn implementacj klasy ,
:
Rozdzia 5.
139
##4G;>6NE9>P4(/
##4GPQ6NE9>P4(J
G#
G#
'$
$G+'#
#
#
G#('$($G+'#(
#(
#
$G+'#/$G+'#"/
#/
#"/
#G;>6NE9>P
#"G;>6NE9>P
#!GPQ6NE9>P
#"GPQ6NE9>P
!"
!'$"'$
!$G+'#"$G+'#
!
#"
#
!
#"
#
&
!$G+'#
&
'
#
4'$M4 !'$4*!4
#
4O
'*'$+'#M4 !$G+'#4*!4
#
4E#M4 !
#4*!4
#
4N
#M4 !
#4*!4
&
$,
##
&
!
Teraz, gdy mamy zdefiniowan klas macierzyst, moemy zastosowa sowo kluczowe
-
, aby odziedziczy atrybuty i metody po tej klasie i zdefiniowa klas potomn klasy
,
wyspecjalizowan pod ktem konkretnego typu mediw, na przykad ksiek lub
filmw. Klasa wyspecjalizowana, powstaa wskutek dziedziczenia po klasie macierzystej,
nazywana jest klas potomn lub podklas. Przedstawiamy klas ., ktra jest klas
potomn klasy ,
. Pozostae klasy mona zdefiniowa w podobny sposb.
Dobr praktyk programistyczn jest tworzenie podklas na podstawie elementu, ktry
w przypadku podejcia proceduralnego wymuszaby wiele rozgazie kodu. W naszym
przykadzie jest to atrybut , ktry zmusza nas do tworzenia rozbudowanych instrukcji
. Wyeliminowanie tego atrybutu i utworzenie klasy na podstawie informacji, ktre
przechowywa, pozwoli nam znacznie ograniczy komplikacje logiki w naszej aplikacji.
'
140
Rozdzia 5.
141
Powysza instrukcja po prostu wywoa metod klasy 1. o nazwie %2.
Jeli metoda o podanej nazwie nie istnieje w definicji klasy, interpreter PHP zasygnalizuje
bd.
Wrmy do przykadu klasy .. W metodzie wykorzystalimy wywoanie:
G#MM$'
142
Wszystkie klasy potomne (takie jak /, . czy %) bd posiaday t sam liczb
danych i funkcji, co klasa macierzysta, lub bd posiaday dodatkowe atrybuty i metody,
niedostpne w klasie macierzystej. Innymi sowy, klasy potomne s zwykle lepiej wyposaone w funkcje od ich klasy macierzystej.
Polimorfizm
Polimorfizm jest kolejn cech programowania obiektowego, ktra pozwala na traktowanie
obiektw w jednolity sposb. Moemy wykorzysta moliwoci istniejcych klas, a take
dowolnych ich klas potomnych zdefiniowanych w przyszoci, pozostawiajc interpreterowi
wszelkie szczegy dotyczce rnic pomidzy klasami. Polimorfizm powoduje, e bardzo
atwo jest dodawa nowe klasy do systemu bez wprowadzania bdw w istniejcym kodzie.
Wrmy do przykadu ze sklepem z artykuami multimedialnymi. Gdy uytkownik systemu zada listy nowych artykuw, nie powinno mie znaczenia, czy to ksika, film czy
pyta CD. W tym miejscu wkracza wanie polimorfizm. Technika ta pozwala traktowa
obiekty reprezentujce wymienione media w jednakowy sposb. Nie musimy kopota si
sprawdzaniem typw zmiennych przy uyciu instrukcji 3 lub . Zadanie to pozostawiamy interpreterowi PHP.
Polimorfizm jest technik atw do opanowania, gdy rozumiemy ju zasady dziedziczenia,
poniewa jedynym sposobem uzyskania zjawiska polimorfizmu jest dziedziczenie. Dziedziczenie pozwala na tworzenie abstrakcyjnej klasy macierzystej, a nastpnie implementowanie metod tej klasy w klasach potomnych. W naszym przykadzie wszystkie klasy
potomne posiadaj wasne metody suce prezentacji informacji na ich temat. Nasza klasa
macierzysta zawiera metod , co gwarantuje nam, e wszelkie klasy potomne bd
posiada t sam metod. Oto przykad:
#
##"#$'(#$E(#$'(#$E
#
#
###
##
#
## !$'
#
4*!*!4
&
Powyszy kod wypisze kolejno informacje na temat kadego obiektu medium, niezalenie
od tego, czy to jest CD, ksika, czy te film lub te program komputerowy. Pomimo istnienia rnic w klasach potomnych klasy ,
, moemy traktowa je podobnie, poniewa wszystkie posiadaj metod . Interpreter PHP rozpozna sytuacj i zdecyduje,
co naley zrobi.
Rozdzia 5.
143
Przedstawiony kod demonstruje eleganckie rozwizanie problemu wypisania listy artykuw w sklepie. Jest ono o wiele prostsze od rozbudowanego rozwizania opierajcego si
na technice przedstawionego wczeniej programowania proceduralnego. Zamy, e musimy
doda klas o nazwie 1.
. Dodamy now klas potomn klasy ,
i utworzymy
kilka obiektw nowej klasy w tablicy
, a nasza metoda wypisania elementw nie
bdzie wymaga adnych zmian:
#
##12"#$+>
#
#
#
###
##
#
## !$'
#
4*!*!4
&
!
Powyszy kod wypisze istniejc list, a take nowo utworzony obiekt klasy 1.
.
Zwr uwag na to, e nie musielimy wprowadzi jakichkolwiek zmian w instrukcji 3
. Polimorfizm umoliwia tworzenie takiego wanie kodu, atwego w rozbudowie i zrozumieniu. Dziedziczenie samo w sobie posiada niewiele zalet. Uywamy dziedziczenia,
aby skorzysta z zalet polimorfizmu, ktry pozwala nam tworzy kod przejrzysty i atwy
w rozbudowie. Dziedziczenie nie jest tylko sposobem na ponowne wykorzystanie kodu, jak
zauwaylimy wczeniej, jest przede wszystkim sposobem na udostpnienie polimorfizmu
w kodzie aplikacji. Gdy zapoznamy si z rnymi ukadami projektowymi, uzmysowimy
sobie, jak wiele problemw programistycznych mona rozwiza dziki wykorzystaniu
dziedziczenia i polimorfizmu.
Metody abstrakcyjne
Gdy stosujemy dziedziczenie, czsto klasa macierzysta definiuje metody nie zawierajce
kodu, poniewa zdefiniowanie mechanizmw w postaci wsplnej dla wszystkich klas potomnych nie jest moliwe. Technik tak, zwan metodami abstrakcyjnymi, wykorzystujemy, aby zaznaczy fakt, e metoda nie zawiera kodu i programista implementujcy
klasy potomne musi zaimplementowa mechanizmy tych metod. Jeli metoda nie zostaje
przesonita (co zostao omwione w podrozdziale Dziedziczenie), nadal nie bdzie realizowa adnych zada.
Jeli nie zdefiniujemy metody abstrakcyjnej, a klasy potomne nie przesoni jej, zostanie
wywoany bd wykonania zgaszajcy brak metody w obiekcie. Dlatego wane jest definiowanie pustej metody w sytuacji, gdy nie chcemy lub nie moemy zdefiniowa adnego
mechanizmu dziaania metody.
W terminologii obiektowej zdefiniowanie metody jako abstrakcyjnej z reguy wymusza
na programicie przesonicie jej w klasie potomnej. PHP nie obsuguje takiego wymuszenia z powodu ogranicze w zaimplementowanym modelu obiektowym. Osoby implementujce klasy potomne powinny zapozna si z dokumentacj klas macierzystych, aby okreli, ktre z metod powinny zosta przesonite.
Pomimo braku sw kluczowych w PHP, ktre definiowayby metody abstrakcyjne, przyja si notacja uywana przez programistw dla wskazania metody abstrakcyjnej. Aby
wskaza osobie implementujcej klasy potomne, e metoda jest abstrakcyjna i powinna zosta przesonita, definiujemy j jako pust. W naszym przykadzie metoda abstrakcyjna
jest zaznaczona pogrubion czcionk:
144
7
$
#
'$
7
$#('$
!#"#
!'$ "'$
&
*#';#
# !#
&
*#'>'$
# !'$
&
&
!")"*""+ "#$%
&
!
Rozdzia 5.
145
Handlowiec moe otrzymywa miesiczn pensj, ale moe te otrzymywa dodatek obliczany na podstawie wielkoci zysku, ktry przynis firmie w danym miesicu. Poniej
przedstawiamy implementacj klasy 4
, ktra realizuje powysze zaoenia:
#T#6
#4U# 4
##4UNGVO>P67W9G;P4(-J
F
$#
F
$#
#R#U#
#
#$ AC / $
'#'
'*'# '#
$
F
$#
#('$ (#(
#($
'#'
U# MMU# #('$ (#
!
7###
!
L
'#'$
'#'
&
7###
#/XX#!-#"UNGVO>P67W9G;P
!#"#
&
L
'#'$
'#'
$
'#'/$
'#'"/
!$
'#'"L
'#'
&
*#'G##
'#% *
#U# MM *#'G##
'#% *0
!#Y !$
'#'
&
&
!
146
Adekwatno i powizania
Omwilimy ju sposb przechowywania danych wewntrz obiektw, a take wykorzystalimy wicej ni jedn klas w celu rozwizania problemu. W tym miejscu napotykamy
pojcia adekwatnoci oraz powiza klas.
Adekwatno jest stopniem dostosowania atrybutw i metod do potrzeb obiektu. Czy metody i atrybuty klasy s cile powizane, powodujc, e obiekt jest w duym stopniu dostosowany do swojego przeznaczenia, czy te obiekty tej klasy s zmuszone do realizacji
setek rnych zada?
Niektrzy programici nie zdaj sobie sprawy z potencjau drzemicego w programu
obiektowym, cho by moe s skuteczni w tworzeniu oprogramowania wykorzystujcego
obiekty. Utworzenie moduu i opakowanie go w klas nie wystarczy, by rozwizanie takie
byo naprawd zorientowane obiektowo. Obiekty tworzone w ten sposb w rzeczywistoci
realizuj zadania caego programu w ramach jednej klasy. Przyjrzyjmy si przykadowi,
w ktrym pominito implementacj metod, aby zademonstrowa podejcie do programowania obiektowego charakteryzujce si niskim poziomem adekwatnoci, polegajce na
implementacji caoci w postaci pojedynczej klasy boskiej. W tym przykadzie zademonstrujemy mechanizm formularzy, ktry sprawdza poprawno wprowadzanych danych,
wypisuje kod formularza, a take generuje kod JavaScript do obsugi formularza:
#
':
'
'#
#
##:
'
#:
'
'
$ ':
'&
9
##:
'
'('$($
(*&
$'7 $
:
'
'&
$'7 $
9
###
##:
'&
+## =
#
##:
'&
*#' =
9
##:
'#
##:
'&
$':
'
'&
$'9
##:
'#
##:
'&
:
'
'&
&
Rozdzia 5.
147
Jak wida w powyszym przykadzie, zastosowanie nieadekwatnych klas prowadzi do powstania klas boskich i stanowi bdne podejcie do rozwizania problemu. Przedstawiony
przykad nie wykorzystuje zalet programowania obiektowego. Gdy projektujesz klas, staraj si j zminimalizowa tak, jakby to bya funkcja. Najlepszym podejciem jest specjalizacja funkcji w sposb, ktry zapewnia jak najdoskonalsz realizacj pojedynczego zadania. Dokadnie ta sama zasada dotyczy obiektw. Gdy wystpi konieczno wprowadzenia
zmian w kodzie, bdziesz wiedzia dokadnie, gdzie go szuka. To znacznie upraszcza proces usuwania bdu, oszczdzajc nam koniecznoci przegldania tysicy wierszy kodu
w ramach pojedynczego pliku. Dlatego naley powici sporo uwagi projektowi klas i odpowiedniemu oddzieleniu logiki od danych, poniewa tworzenie wysoce adekwatnych
obiektw jest w dalszej perspektywie bardzo korzystne.
Przeniemy nasz dyskusj na zagadnienia zwizane z powizaniami.
Pojcie powiza dotyczy liczby wzajemnych relacji pomidzy dwoma lub wiksz liczb
obiektw. Gdy mamy do czynienia z dwoma obiektami, ktre s wiadome wzajemnego
istnienia, mwimy o silnych powizaniach. Mona to porwna do bdnego zdefiniowania kanaw komunikacyjnych celem wymiany informacji pomidzy kilkoma osobami.
W tym przypadku kady ma powizania z prawie kadym:
A
E
D
Powyszy diagram przedstawia pi obiektw, z ktrych kady ma powizania z przynajmniej jednym z pozostaych. Strzaki okrelaj kierunek komunikacji (jedno bd dwukierunkow). Obiekt D zawiera kod, ktry zakada istnienie obiektw A, C oraz E. Podobnie
obiekty A, C oraz E zawieraj kod, ktry zakada istnienie obiektu D. Poniewa obiekt D
wykorzystuje dwustronn komunikacj z pozostaymi obiektami, wida od razu, e zosta le
zaprojektowany. Przyjmijmy, e moemy doda nastpn klas, aby rozbi powizania
w nastpujcy sposb:
A
E
X
148
Czsto atrybuty s pomijane, a wyliczone zostaj tylko metody. To zaley od tego, jak duo
czasu potrzebujesz na zapisanie swoich koncepcji.
Wyliczenie atrybutw wraz z metodami jest dobr praktyk, szczeglnie w przypadku
wsppracy z bazami danych.
Rozdzia 5.
149
Teraz, gdy znamy sposb modelowania prostych klas, przyjrzyjmy si sposobowi modelowania bardziej skomplikowanych klas zawierajcych inne klasy. Nie przedstawiamy ich jako atrybuty klasy. Przedstawiamy je jako dwa diagramy klas w UML-u i czymy je lini
z symbolem rwnolegoboku w nastpujcy sposb:
Klasa 1
atrybut 1
...
atrybut N
metoda 1
...
metoda N
Klasa 2
atrybut 1
...
atrybut N
metoda 1
...
metoda N
Ten diagram przedstawia, e .
" jest zagniedona w .
. Nasz przykad klasy
mona zobrazowa nastpujco:
Kluczyk
pasuje()
Samochod
start()
stop()
ustalPredkosc()
Silnik
start()
stop()
pracuje()
Oznacza to, e zagnieda w sobie obiekty klas 2 oraz . Wypenione
rwnolegoboki oznaczaj, e komponenty musz zosta utworzone w celu prawidowego
funkcjonowania obiektu, w ktrym s zagniedone. Pamitajmy, e za prawidow inicjacj
wszelkich atrybutw klasy odpowiedzialne s konstruktory. Analizujc powyszy diagram,
programista widzi, jakie obiekty musz zosta utworzone w celu udostpnienia wszelkich
usug obiektu nadrzdnego.
Moliwe jest rwnie zastosowanie symbolu pustego (niewypenionego) rwnolegoboku
w diagramie powiza obiektw. Zastosowanie tego symbolu wskazuje, e nie ma koniecznoci inicjacji obiektu w celu prawidowego funkcjonowania klasy nadrzdnej. Oto przykad dodania obiektu klasy / do klasy :
Samochd
start()
stop()
ustalPredkosc()
utworzOdtawrzaczCd()
OdtwarzaczCd
odtwarzaj()
stop()
pauza()
Nie wszystkie samochody musz mie zainstalowane odtwarzacze CD, wic sygnalizujemy
ten fakt, stosujc symbol pustego rwnolegoboku. W przypadku wystpowania obiektw,
ktre nie musz by inicjowane w konstruktorze klasy nadrzdnej, naley zastosowa metod fabryczn (omwion wczeniej) suc do utworzenia takiego obiektu, na przykad
/ w przypadku naszej klasy . Rnica w stosunku do klas
oraz 2 polega na tym, e nie udostpniamy metod fabrycznych
czy te 2
w klasie , poniewa nie maj one sensu w sytuacji, gdy obiekty wspomnianych klas s inicjowane w konstruktorze.
150
Data
jestPrzed()
jestPo()
jestRowna()
sklonuj()
pobierzDzien()
pobierzDzienTygodnia()
...
Skoro poznalimy sposb modelowania zagniedania obiektw, przejdmy do sposobu modelowania dziedziczenia. W naszym przykadzie sklepu z multimediami mielimy do czynienia z rnymi rodzajami mediw, na przykad z ksikami, pytami CD czy te filmami.
Utworzylimy klas macierzyst o nazwie ,
, a nastpnie utworzylimy jej klasy potomne w celu reprezentacji rnych typw mediw dostpnych w naszym sklepie. Aby
przedstawi zwizki dziedziczenia pomidzy klasami ., / i innymi a klas ,
,
uyjemy symbolu wypenionego trjkta czcego za pomoc linii klas macierzyst z klasami potomnymi. Oto model w UML-u dla naszego sklepu z multimediami:
Medium
kup()
wypiszMedia()
wypisz()
Ksiazka
wypisz()
CD
wypisz()
Oprogramowanie
wypisz()
Film
wypisz()
Warto zwrci uwag, e nie ma potrzeby wyliczania w diagramach klas potomnych wszystkich metod klasy macierzystej. Z zaoenia wiadomo, e wszystkie klasy potomne posiadaj metody klasy macierzystej. Dobr praktyk jest jednak umieszczanie nazw metod klasy
macierzystej przesonitych w klasach potomnych, jak metoda z naszego przykadu.
Gdy klasy rozrastaj si, mona rwnie pomin je dla oszczdzenia miejsca. Oczywicie,
mona rwnie zastosowa kolejne dziedziczenie, na przykad klasa % moe mie klasy
potomne o nazwach 64 oraz 565, o ile taka decyzja stanowi waciwe rozwizanie upraszczajce implementacj. W dalszej czci rozdziau zajmiemy si analiz przypadkw,
w ktrych lepiej zastosowa dziedziczenie oraz innych, ktre s lepiej reprezentowane w postaci zagniedania obiektw. W tej chwili jednak zajmijmy si specyficznym typem zawierania, nazywanym delegacj.
Delegacja
Delegacja jest specyficzn odmian zawierania si obiektw suc ponownemu wykorzystaniu kodu obiektw. Gdy klasa ma za zadanie udostpnienie usugi, moe po prostu
Rozdzia 5.
151
oddelegowa jej realizacj obiektowi, ktry jest w niej zawarty i po prostu przekaza wynik.
Uywajc delegacji, obiekt nie posiada fizycznego powizania, jak na przykad silnik z samochodem. Jedynym zadaniem obiektu zawartego w obiekcie nadrzdnym jest udostpnienie
usugi w celu uproszczenia projektu obiektu nadrzdnego i uczynienia go bardziej spjnym.
Jako przykad utworzymy obiekt formularza, ktry wypisuje i sprawdza poprawno danych formularzy WWW. Jednym z projektw mogoby by sprawdzanie danych wewntrz
obiektu formularza. Jednake nie jest to najlepsze rozwizanie. O wiele lepiej byoby utworzy osobn klas obiektu sprawdzajcego poprawno i wykorzysta go do udostpnienia
metod sprawdzania poprawnoci danych formularza, w ktrym obiekt kontrolny jest zawarty.
Oto diagram w UML-u ilustrujcy ten przykad:
Formularz
dodajElement()
dodajPrzycisk()
weryfikuj()
wypisz()
ustalStyl()
pobierzKomunikatOBledzie()
WeryfikatorDanych
dodaj()
weryfikuj()
pobierzKomunikatOBledzie()
Obiekt klasy 7
35 jest zawarty w obiekcie klasy % i jest tworzony
w trakcie jego tworzenia. Dlaczego postpujemy w ten sposb? Zamy, e potrzebujemy
obiektu weryfikujcego dane w innej aplikacji, na przykad w programie e-mailowym.
W innym przypadku konieczne byoby ponowne zakodowanie mechanizmw klasy 7
3
5 w kadej nowej aplikacji. Lepiej jest utworzy klas 7
35, ktr
mona wykorzysta w kadej chwili, gdy wyda si potrzebna.
Zgodnie z nasz wczeniejsz dyskusj dotyczc adekwatnoci, klasa % zachowuje
si w sposb kojarzcy si z klas bosk, obsugujc elementy formularza, kod JavaScript,
wypisywanie formularza z uwzgldnieniem formatowania i weryfikacji danych. Rozsdniej
byoby umieci obsug tych zada w osobnych klasach i po prostu delegowa zadania
klasy %.
Kolejn wan obserwacj jest to, e klasa % jest wiadoma istnienia klasy 7
3
5, lecz klasa 7
35 nie wie nic o tym, e jest zawarta w klasie %
. Dzieje si tak, poniewa klasa 7
35 nie posiada adnego odwoania
do klasy %. Dziki temu komunikacja pomidzy klasami jest jednokierunkowa zamiast dwukierunkowej. A zatem wykorzystujc moliwoci delegacji, zmniejszylimy liczb
powiza obiektw. Bardzo wane jest poznanie moliwoci ponownego wykorzystania
kodu, poniewa celem programisty powinno by tworzenie adekwatnych obiektw, ktre s
ze sob bardzo luno powizane. Przeanalizujmy poniszy przykad.
Przykad prezentuje trzy metody delegujce zadania do klasy 7
35. Pierwsz
metod jest 2&
, ktra zgasza obiektowi klasy 7
35 warto, typ
oraz komunikat o bdzie dotyczce elementu formularza.
Y
U # $#
##
''+)'+ $# $
9
###
##
!#
##12"#
##
Y
152
Y
Rozdzia 5.
153
7
R
7R(
!$QR
!$V
&
$QR
!R"R
&
$V
!"
&
$
!
"
&
*#'Q
# !R
&
*#'V
# !
&
*#'
# !
&
&
&
Na pierwszy rzut oka wyglda to na niez reprezentacj punktu na paszczynie. Przyjrzyjmy si jednak moliwociom zastosowania takiej klasy:
"#$7/(@/
!
R" ! *#'Q
R0"H.
" ! *#'V
0"IK
!$QR
!$V
!
7
R
154
Zobaczmy, jak bardzo uproci si nasz kod i w jaki sposb osignlimy hermetyzacj
obiektu. Wykorzystanie klasy jest podobne jak w poprzednim przykadzie:
"#$7/(@/
!'#H.(IK
!
get_class()
",,-#$
Funkcja
zwraca nazw klasy obiektu. Szczeglnie uyteczna jest podczas procesu wyszukiwania i usuwania bdw, umoliwiajc sprawdzenie, czy w programie bior
udzia waciwe obiekty. Na przykad, gdy posiadamy metod oczekujc obiektu klasy
9, moemy zastosowa t funkcj w celu usprawnienia wyszukiwania bdw:
Rozdzia 5.
155
'
' $
#+#6
' $""<' $<
# !$'
"" !$+L'
##
&
#
#
&
Funkcja
umoliwia weryfikacj poprawnoci danych i jest uyteczn alternatyw funkcji 2
sprawdzajcej, czy argument jest obiektem klasy. Taka moliwo pozwala na zaoszczdzenie czasu podczas usuwania bdw w aplikacjach wykorzystujcych wiele powiza pomidzy obiektami rnych klas.
Naley zwrci uwag na fakt, e PHP zamienia nazwy klas na mae litery, naley wic
w porwnaniach stosowa nazwy klas skadajce si z maych liter. W naszym przykadzie porwnywalimy wynik dziaania funkcji
z napisem zamiast 9.
Porwnanie z napisem 9 daoby wynik negatywny, ponadto wywoaoby bd asercji.
get_parent_class()
",,-)-#$
Funkcja ta jest szczeglnie uyteczna podczas sprawdzania poprawnoci kodu wykorzystujcego mechanizmy polimorfizmu. Nie bdzie potrzebna w ostatecznej wersji aplikacji,
poniewa w tym przypadku wszystkie obiekty powinny by egzemplarzami klas potomnych prawidowo skomponowanych klas macierzystych. Jeli zaoenie takie nie jest spenione, tworzona aplikacja zawiera powane bdy koncepcyjne. Oto fragment kodu kontrolnego w metodzie polimorficznej:
$'L'
#
!#
###
##
#+#6#6
#
##""<#
##<
#
## !
&
#
#
&
Funkcja oczekuje tablicy elementw bdcych egzemplarzami klas potomnych klasy &
i w kolejnoci wypisuje je na wyjcie. Program stosuje asercj zakadajc przynaleno
kadego elementu do klasy potomnej klasy &
. Kod podobny do powyszego moe okaza si uytecznym w trakcie usuwania bdw, lecz powinien by wyczany w rodowisku
produkcyjnym. Wicej informacji na temat usuwania bdw znajdziesz w rozdziale 6.
Ograniczenia PHP
Jak wspomnielimy wczeniej w tym rozdziale, implementacja technik zorientowanych
obiektowo w PHP posiada swoje ograniczenia. W tym podrozdziale omwimy najczciej
wspominane ograniczenia PHP, takie jak brak atrybutw statycznych, brak destruktorw
oraz brak wielokrotnego dziedziczenia.
156
=*
#%#' #
Konstruktor klasy : zawiera kod zwikszajcy o jeden warto zmiennej globalnej
:
, co odzwierciedla fakt utworzenia nowego jabka.
=*
+
*
'*=*
#
'*=*
#00
!#%#' #"
#
&
Z kolei metoda 2
zmniejsza o jeden warto zmiennej globalnej :
:
'#'
\ !#%#' #
+
*
'*=*
#
'*=*
#
!#%#' #"#
&
&
#%#' #
# !#%#' #
&
Zwr uwag, e zmienna globalna zostanie zmniejszona wycznie w przypadku, gdy jabko
nie zostao jeszcze zjedzone. Pozwala to na zachowanie spjnoci emulowanego atrybutu
statycznego. Na kocu definiujemy metod zwracajc liczb istniejcych w pamici obiektw klasy ::
Rozdzia 5.
157
#
'
'*
+
*
'*=*
#
#
'*=*
#
&
&
-"#$=*
$
'*=*
#."#$=*
$
'*=*
#.
H"#$=*
$
'*=*
#H
#
=*
MM
'*4*!4$#H
- !'#'$
'*=*
#.
. !'#'$
'*=*
#@"#$=*
$
'*=*
#.
#
=*
MM
'*4*!4$#.
!
Mimo e stosowanie zmiennych globalnych jest powszechnie uwaane za nieeleganckie, zastosowanie tej metody w celu zasymulowania atrybutu statycznego w PHP jest
cakiem efektywne.
Po wywoaniu powyszego kodu przegldarka wywietli liczby oraz ", zgodnie z komentarzami w powyszym kodzie. Emulowanie atrybutw statycznych to uyteczna technika,
lecz naley by wiadomym problemw zwizanych z jej stosowaniem:
inne obiekty mog bez problemu zamaza (usun) zawarto zmiennej globalnej,
jeli nie s wiadome wykorzystania jej w charakterze atrybutu statycznego.
Wymienione problemy s typowe dla stosowania zmiennych globalnych, wic symulowanie atrybutw statycznych za pomoc zmiennych globalnych nie stanowi wyjtku.
Brak destruktorw
Konstruktory inicjuj stan obiektw tak, aby mona byo z nich korzysta natychmiast po
utworzeniu. Inn koncepcj programowania zorientowanego obiektowo jest pojcie destruktora, uywanego do usuwania atrybutw obiektu, w tym zagniedonych obiektw, lub te
wykonania innych czynnoci zwizanych z koczeniem dziaania obiektu, jak na przykad
zamykania poczenia z baz danych. W PHP nie istnieje moliwo likwidowania obiektw w ten sposb. Zamiast tego PHP po prostu usuwa z pamici obiekty utworzone przez
skrypt w momencie zakoczenia dziaania skryptu.
158
U#
#('$
U# #('$
!#"#
!'$ "'$
&
'''7
$#
$
''D'D
$#
&
7
$ $
$
$)
D
#,
$ $
&
&
!
Nie ma tu na razie nic nadzwyczajnego. Ta klasa macierzysta zawiera dwie metody umoliwiajce dyrektorowi zarzdzanie pracownikami oraz wypacanie im pensji, czyli to, czego
nie robi inynierowie.
'#
;'#
#('$
;'##('$ ( ';'#
!#"#
!'$ "'$
&
Rozdzia 5.
159
# #
'D
#B# $
&
*#'W ';'#
# ! ';'#
&
&
!
Klasa ;
udostpnia metod definiujc projekty prowadzone przez inyniera. Chcc
zdefiniowa klas implementujc dyrektora technicznego, oczekujemy, e bdzie zarzdza inynierami, zatwierdza ich listy pac i rozdziela im projekty. Zastosujmy wic nasz
sztuczk z dziedziczeniem i delegacj, aby zasymulowa wielokrotne dziedziczenie.
U# 8#
'#R#U#
'#
Klasa 5
$
dziedziczy po klasie 5
, wic zawiera te same atrybuty oraz
metody co klasa macierzysta. Aby udostpni mechanizmy klasy ;
, zagniedzimy
klas ;
wewntrz klasy 5
$
, a w konstruktorze umiecimy inicjacj
tego obiektu:
U# 8#
'#('$ ( ';'#
U# MMU# #('$
!'#"#$;'##('$ ( ';'#
&
# #
!'# ! # #
&
*#'W ';'#
# !'# ! *#'8;'#
&
&
# 8#
'"#$U# 8#
'<=<(< $
<(<G#
<
!
160
Na pierwszy rzut oka moe wydawa si, e realizacja powyszych zada wymaga utworzenia skomplikowanego moduu. Jednak dziki odpowiedniemu projektowi architektury
moemy osign zadowalajce wyniki bez wprowadzania zbdnej komplikacji. W rzeczywistoci istnieje bardziej elastyczny projekt mechanizmu formularzy, ni ten, ktry chcemy
zademonstrowa, jednake wymaga on zastosowania wielu klas zewntrznych. Celem naszego przykadu jest zademonstrowanie wszystkich koncepcji, ktre przedstawilimy do tej
pory. Chcemy pokaza, w jaki sposb mona rozwiza problem utworzenia mechanizmu
formularza WWW z zastosowaniem obiektw.
Na pocztku naley zdefiniowa klas %, poniewa to ona jest gwn klas w naszym mechanizmie. % powinien umie wypisa swoj zawarto, uywajc definicji
stylu, dodawa elementy i przyciski, tworzy kod weryfikujcy dane w JavaScripcie dziaajcy
po stronie klienta, weryfikowa swoje dane po stronie serwera, a take wypisywa komunikat o bdzie w przypadku problemw z weryfikacj danych.
Rozdzia 5.
161
Nastpnie potrzebna nam bdzie struktura obiektw modelujca wszelkie moliwe elementy formularzy oraz przyciski. Zastosujemy klas macierzyst o nazwie &
%
i rozszerzymy j za pomoc dziedziczenia tak, aby obejmowaa wszystkie elementy
formularza. Takimi elementami mog by pola tekstowe, pola daty, due pola tekstowe, hasa, pola wysyki plikw czy te listy wielokrotnego wyboru. Tworzc klas macierzyst
&
% i wykorzystujc moliwoci polimorfizmu, moemy dodawa dowoln
liczb typw elementw formularza bez koniecznoci modyfikacji logiki definiujcej wypisywanie, weryfikacj oraz generowanie kodu w JavaScripcie. Przyjrzyjmy si naszemu modelowi obiektowemu:
Formularz
dodajElement()
dodajPrzycisk()
weryfikuj()
wypisz ()
generujJ avaScript()
ustalStyl()
pobierzKomunikatOBledzie()
PoleTekstowe
PoleHasa
DuePoleTekstowe
Tablica
elementw
formularza
ElementFormularza
wypiszElementFormularza()
wypisz()
pobierzParametrHtml()
PoleUkryte
WyborPliku
PoleDaty
ListaWyboru
dodaj()
ustalWielokrotnyWybor()
GrupaPrzelacznikow
dodaj()
ListaWielokrotnegoWyboru
pobierzH tml()
GrupaOpcji
pobierzHtml()
Ten model wykorzystuje niemal t sam standardow hierarchi zagniedania i dziedziczenia, ktr omwilimy przy okazji omawiania wczeniejszych przykadw w tym rozdziale, z dwoma wyjtkami. Po pierwsze, schemat pokazuje, e elementy formularza nie s
zawarte w obiekcie formularza. Chocia fizycznie elementy s skadowymi formularza, zachowuj si inaczej w momencie jego utworzenia. Dodalimy metody 2&
oraz
2# suce do dodawania elementw do formularza. Formularz nie posiadajcy elementw jest nadal penoprawnym, cho niezbyt uytecznym obiektem klasy.
Druga komplikacja dotyczy zwizkw zawierania oraz metody 2 w klasach =7
oraz =7
7. Pozwala to na dodawanie elementw do pola wyboru
w ten sam sposb, w jaki mona to zrobi w przypadku formularza. Mechanizm ten jest
praktycznie przezroczysty dla programisty. Znaczenie naszego kodu polega na tym, e metoda kadej z klas potomnych klasy &
% moe zosta zrealizowana
w dowolny sposb. Moemy wypisa znaczniki elementw pola wyboru w dowolny sposb, nie naruszajc adnej z zasad opisanych w modelu dziedziczenia. Mniejsze, lecz podobne modele dziedziczenia moemy zdefiniowa dla przyciskw:
162
Tablica
elementw
formularza
ElementFormularza
wypiszElementFormularza()
wypisz()
PrzyciskZatwierdzajacy
PoleDaty
Posiadamy ju solidny fundament dla struktur formularzy, lecz w jaki sposb zadba o ich
atrakcyjny wygld? Zastosujemy osobn klas %, co pozwoli nam na dowolne
definiowanie stylu formularza. W naszym przypadku zdecydowalimy si na wykorzystanie HTML-u. Czsto logika prezentacji jest umieszczana w tym samym miejscu, co logika
aplikacji, lecz nie jest to dobra praktyka. Komponenty stylu lub elementy dekoracyjne pozwalaj na umieszczenie logiki prezentacji osobno, dziki czemu nasz obiekt jest bardziej
spjny. Dodatkow korzyci pync z oddzielenia elementw dekoracyjnych od logiki
obiektu jest to, e mona zmieni sposb prezentacji obiektu bez zmiany logiki obiektu, dziki czemu atwiej go rozbudowywa i stosowa w nowym projekcie.
W celu zdefiniowania stylu formularzy wykorzystamy moliwo delegacji. Jednym ze stosowanych ukadw projektowych jest zastosowanie zewntrznego obiektu dekoratora.
Dziki strukturalnej naturze jzyka HTML atwo jest zrealizowa tak funkcj za pomoc
obiektu osadzonego. Dziki temu diagram przepywu informacji pomidzy obiektami jest
o wiele czytelniejszy bez negatywnych efektw ubocznych, poniewa moemy osign te
same moliwoci, co w przypadku zastosowania zewntrznego obiektu dekoratora.
Klasa % zostaa rozszerzona o trzy klasy potomne. Klasa 5 jest
wykorzystywana przez konstruktor klasy %. Pozostae dwie klasy reprezentuj dowolne style, ktre mona zastpi wasnymi, w zalenoci od upodoba. Dziki takiemu
projektowi moemy tworzy efektowne formularze, definiujc nowe obiekty stylu.
' !$
#$
:'
' !$'
StylFormularza
wypiszN aglowekFormularza()
wypiszStopkeFormularza()
wypiszElementNaglowka()
wypiszElementStopki()
wypiszPrzyciskNaglowka()
wypiszPrzyciskStopki()
StylDomyslny
StylKlasyczny
StylFantazyjny
Rozdzia 5.
163
WeryfikatorDanych
dodaj()
weryfikuj()
pobierzKomunikatOBledzie()
pasuje()
Tablica
formularzy
Formularz
dodajElement()
dodajPrzycisk()
weryfikuj()
wypisz()
generujJavaScript()
ustalStyl()
pobierzKomunikatOBledzie()
164
Ojej, nie ma ani kawaka kodu implementacji? Co robi? Na to pytanie atwo odpowiedzie
napisz to. Jeli masz zamiar nauczy si programowania zorientowanego obiektowo
i doceniasz koncepcje, ktre tutaj poznae, Twoim pierwszym zadaniem powinno by dokoczenie tego moduu. Nie bdzie to strata czasu, poniewa bdziesz mg wykorzysta
ten kod w wielu programach. Poegnaj si z tymi wszystkimi darmowymi moduami znajdowanymi w Sieci i zacznij stosowa elementy utworzone wasnorcznie.