Wraz ze wprowadzeniem PHP w wersji piątej do ogólnoświatowego "obiegu", możliwość wykorzystania wszystkich cech i zalet programowania obiektowego wzrosła do prawie 100%. Jednakże w tym samym momencie nie wzrosły umiejętności koderów i w większości przypadków nadal programują oni strukturalnie. W artykule tym postaram się przybliżyć OOP (ang. object-oriented programming) i podać, prawie jak na tacy, podstawy oraz dobre nawyki. Jednym słowem - zachęcić Was do przejścia na "obiektówkę".
Pewnie zastanawia Was słowo "dziedziczyć", którego użyłem w powyższej liście. Dziedziczenie polega na stworzeniu obiektu pochodnego. Przykładowo, obiekt Kwadrat jest obiektem pochodnym od obiektu Figura. Jeśli chcielibyśmy to zapisać językiem PHP:
<?php class Figura {} class Kwadrat extends Figura {} ?>
Konstruktor i destruktor to dwie magiczne metody, które wywoływane są w momencie utworzenia instancji obiektu oraz, odpowiednio, w momencie jej zniszczenia. Do PHP 5 konstruktor tworzono nazywając metodę nazwą klasy. Destruktorów nie było - jest to nowa funkcjonalność, dostępna dopiero od "piątki". Przykładowy kod definiujący konstruktor i destruktor wygląda tak:
<?php class Kwadrat extends Figura { public function __construct() {} public function __destruct() {} } ?>
Dziedziczenie konstruktorów i destruktorów oraz ich wywołanie wygląda podobnie, jak w przypadku zwykłych metod, jednak tutaj należy użyć nazw parent::_construct oraz parent::__destruct.
Użyty już w poprzednich przykładach, konkretyzuje zakres, z jakiego korzystamy przy wywołaniu metody, ale nie tylko. Operatora tego możemy też użyć, jeśli chcemy uzyskać dostęp do jakiejś zmiennej bądź metody statycznej, ale także do stałych klasy. Dużą rolę operator ten spełnia przy instancjach oraz obiektach, których nie inicjujemy. Ponieważ jest to temat do odrębny artykuł, nie będziemy wgłębiać się bardziej w niego.
Czasem potrzebujemy wykorzystać jakąś metodę bądź zmienną bez tworzenia instancji obiektu. Na przykład chcemy wiedzieć, jaka jest definicja (słowna) obiektu typu Trojkat. W tym celu możemy stworzyć statyczną metodę definicjaPola(), która będzie wypisywała na ekran tekst:
<?php class Trojkat extends Figura { public static function definicjaPola() { echo "Pole trójkąta to połowa wysokości * podstawa."; } } ?>
A następnie wywołać ją, korzystając z operatora zakresu:
<?php Trojkat::definicjaPola(); ?>
Stałe klasoweWykorzystanie stałych jest bardzo przydatną praktyką programistyczną. Stałymi mogą być opisy lub identyfikatory dla typowych wartości. Przykładowo, można identyfikować czworokąt za pomocą cyfr: 0 - prostokąt, 1 - kwadrat, ale można stworzyć takie konstrukcje:
<?php class Figura { const KWADRAT = 1; const PROSTOKAT = 0; } class MojaFigura extends Figura { private $typ; public function __construct() { $this->typ = Figura::KWADRAT; } } ?>
Dzięki temu, możemy manipulować identyfikatorami typów, jednocześnie korzystając ze stałych figury, jak ze zmiennych (niemodyfikowalnych) konkretnej przestrzeni nazw. O zaletach takiego wykorzystania stałych pisać nie muszę.
PHP, niestety, nie oferuje pełnego przeciążania operatorów. Nie możemy zatem "dodać" dwóch obiektów do siebie, otrzymując inny (np. dodanie dwóch kwadratów tworzyłoby prostokąt). Możemy jednak, w miarę bezpiecznie, zarządzać danymi wejściowymi i wyjściowymi. Wraz z wydaniem PHP 5.1.0, dostaliśmy poszerzoną listę operatorów, zatem ta część będzie wymagała właśnie wersji 5.1.0 lub wyższej po stronie serwera.Przeciążanie w PHP oznacza "dynamiczne" stworzenie własności i metody. Przykładowo, wcale nie musimy deklarować zmiennej pole, a jednak będziemy mieli możliwość przypisania wartości do, powiedzmy, zabezpieczonej tablicy określającej parametry figury. To samo dotyczy wybierania wartości zmiennych. Przykładowy kod klasy:
<?php class Kwadrat extends Figura { public function __set($nazwa, $wartosc) { $this->parametry[$nazwa] = strip_tags($wartosc); // Przykladowe zabezpieczenie } public function __get($nazwa) { if ( array_key_exists($nazwa, $this->parametry) ) { return $this->parametry[$nazwa]; } else { return NULL; } } } $oKwadrat = new Kwadrat(); $oKwadrat->pole = 25; echo $oKwadrat->pole; ?>
Prócz powyższych __set i __get, mamy dostęp dodatkowo do __isset oraz __unset. Po przykład użycia odsyłam Was do manuala.
Czasem chcielibyśmy, aby wypisanie obiektu na ekran domyślnie wyświetlało nam jeden z jego parametrów. Na przykład, wywołanie echo $oKwadrat; mogłoby domyślnie zwracać pole powierzchni tej figury. Właśnie z tego powodu powstała magiczna metoda __toString(). Nie przyjmuje ona żadnego parametru, a wszystko to, co ona zwróci (return) zostanie wyplute wtedy, gdy zdecydujemy się przedstawić zmienną jako zmienną typu string.
Gdy zachodzi potrzeba zablokowania dalszego nadpisywania metody bądź jej redefinicji, bardzo przydatne jest użycie słówka final przed zapisaniem nagłówka metody. Przykład:
<?php class Figura { final public function foo() { echo "Foo!"; } } class Kwadrat extends Figura { public function foo() { echo "Bar!"; } } $oKwadrat = new Kwadrat(); $oKwadrat->foo(); ?>
W przeciwieństwie do klas abstrakcyjnych, interfejsy służą do budowania zewnętrznej obsługi obiektu, zatem wszystkie metody w interfejsie muszą być typu public. Oczywiście sam interfejs może zawierać tylko nagłówki metod, bez ciała. Użycie interfejsu wygląda mniej więcej tak:
<?php interface iFigura { public function ustawKolor($kolor); } class Figura implements iFigura { public function ustawKolor($kolor) { $this->parametry[$kolor] = "".strtolower($kolor); } } ?>
Bardzo dobrym ułatwieniem, szczególnie dla twórców bibliotek i klas, które będą używane z przez innych programistów, jest konkretyzowanie typów przekazywanych parametrów. Przykładowo, jeśli chcemy, by jakaś metoda przyjmowała tylko zmienną typu array, wystarczy napisać:
<?php class Figura { public function ustawDane(array $dane) { $this->parametry = $dane; } } ?>
Dzięki temu, przekazanie innego parametru (powiedzmy zmiennej typu INT) zakończy się błędem, co zapewne błyskawicznie zostanie wychwycone przez programistę.
Dział programowania obiektowego, nawet w przypadku PHP, jest bardzo rozległy. W artykule tym, nie bez powodu, zabrakło omówienia takich rzeczy jak wzorce (ang. patterns), instancje czy na przykład API do przeglądania struktur obiektu (reverse-engineering dla obiektów). Zagadnienia te wymagają opanowania podstawowych umiejętności programowania obiektowego, a ponadto - są rozległymi i odrębnymi tematami, którym poświęcić trzeba co najmniej tyle samo miejsca, co na ten artykuł. Mam nadzieję jednak, że ten chociaż po krótce wyjaśnia czym jest "obiektówka" i jak zacząć programować obiektowo, odkrywając przy tym jak bardzo w późniejszym etapie może to ułatwić pracę.
Potrzebny jest wyjaśniony przyklad.
Pokazanie sensu kodu.
Patrzę w kod i nic nie rozuimiem.
Pozdrawiam
http://www.php.net/manual/en/language.oop5.typehinting.php - niestety ale to działa tylko dla obiektów i tablic. Przynajmniej na razie Zapomniałeś o tym napisać.
Chyba że (co ćwiczyliśmy na IRCu z miesiąc temu) stworzysz sobie klasę int czy string i będziesz udawał, że piszesz w Javie.
Akurat <literal> to mój błąd edytorski. Poprawione.
- po co "class Trojkat extends Figura" skoro jest to tylko statyczny tekst?
- jaki sens jest pokazywać sam nic nie znaczący zapis bez przykładu? Np. w pierwszym kodzie jest komplikujący tylko przykład fragment <literal class="php"> natomiast zaraz potem sam zapis bez najistotniejszej zawartości która mówiła by po co i na co.
- tam gdzie zapowiada się najciekawiej autor ucina "O zaletach takiego wykorzystania stałych pisać nie muszę. " - a właśnie, że by się przydało.
...i tak cała reszta artykułu niestety, wszystko może i byłoby OK gdyby nie dopisek w tytule "...dla początkujących". Nie zachęca do nauki, przedmówca ma rację, przykładowy kod z komentarzami byłby lepszy od podobnych tajemniczych akapitów jak wyżej .
Witam. Ostatnio interesuję się obiektówką, czasami piszę coś na swoje potrzeby w PHP. Jednak ten artykuł nie do końca dociera do mnie na tyle żeby wszystko w pełni zrozumieć. Większości ludzie, także mnie, łatwiej jest wszystko zrozumieć na konkretnym przykładzie... Na napisanym (nawet rozbudowanym) skrypcie... a następnie omówienie jego elementów. Pozdrawiam