Programowanie obiektowe w PHP
Transkrypt
Programowanie obiektowe w PHP
PHP 5 – język obiektowy Wprowadzenie Klasa w PHP jest traktowana jak zbiór, rodzaj różnych typów danych. Stanowi przepis jak stworzyć konkretne obiekty (instancje klasy), jest definicją obiektów. Klasa reprezentuje problem w postaci obiektu, który agreguje wszystkie czynności i stany z nią powiązane. Aby w PHP utworzyć klasę należy posłużyć się słowem kluczowym class, po którym podaje się jej nazwę. Ciało klasy umieszcza się wewnątrz nawiasów klamrowych, ciałem klasy są właściwości oraz metody. Metody są to funkcje, a właściwości to zmienne. Przykładowa klasa np. class Person może zawierać metody takie jak: setName(), getName(), itp. i może zawierać właściwości takie jak: name, surname, age, itp.. Metoda różni się od zwykłej funkcji wyłącznie tym, że można ją wywoływać tylko w kontekście klasy do której należy, to samo dotyczy właściwości. Każda metoda i właściwość posiadają modyfikator dostępu, który decyduje o ich dostępności na zewnątrz klasy. Modyfikator dostępu podaje się na samym początku definicji metody lub właściwości. Dostępne modyfikatory to: public - metoda lub właściwość dostępna jest wewnątrz oraz na zewnątrz klasy, private - metoda lub właściwość dostępna jest wyłącznie wewnątrz klasy, protected - metoda lub właściwość dostępna jest wewnątrz klasy głównej oraz wewnątrz klasy potomnej. Poniżej przykład prostej klasy: class Person { public $name; public $surname; public function setName($name, $surname) { $this->name = $name; $this->surname = $surname; } public function getName() { return $this->name.' '.$this->surname; } } Utworzenie nowych obiektów klasy Person: $pawel = new Person(); $ola = new Person(); // Ustawienie właściwości name i surname $pawel->name = 'Pawel'; $pawel->surname = 'Kowalski'; $ola->name = 'Ola'; 1 $ola->surname = 'Widera'; Wyświetlenie wyniku metody getName() echo $pawel->getName().'<br />'; echo $ola->getName().'<br />'; Wewnątrz klasy do metod i właściwości należy się odnosić poprzez słowo kluczowe this: $this->propertyName = 'value'; $this->methodName('value'); Po utworzeniu nowego obiektu klasy automatycznie jest uruchamiany konstruktor. Jest to metoda (magiczna – nie jest jawnie wywoływana, lecz automatycznie) o niezmiennej nazwie __construct. Jeśli w ciele danej klasy nie będzie umieszczonego konstruktora to mimo wszystko i tak zostanie uruchomiony domyślny pusty konstruktor, który nic nie będzie robił. Konstruktor jak każda metoda klasy może posiadać parametry, nie może natomiast zwracać żadnej wartości. Poniżej znajduje się zmodyfikowana klasa Person, wszystkie jej właściwości zostały ukryte za pomocą modyfikatora dostępu private, pojawił się natomiast konstruktor wraz z parametrami. class Person { public $name; public $surname; public function __construct($name, $surname) { $this->name = $name; $this->surname = $surname; } … } Tworzenie nowych obiektów klasy Person wraz z parametrami: $pawel = new Person('Pawel', 'Kowalski'); $ola = new Person('Ola', Widera'); W przypadku gdy właściwości klasy (imiona osób) w momencie tworzenia obiektów nie są znane i mają być ustalone dopiero w późniejszej fazie działania programu, bądź zajdzie potrzeba ich zmiany na inne, wtedy parametr w konstruktorze ustawia się w inny sposób. class Person { public $name; public $surname; public function __construct($name, $surname='') { $this->name = $name; $this->surname = $surname; } public function setSurname($surname) { $this->surname = $surname; } 2 … } $pawel = new Person('Pawel'); $ola = new Person('Ola', Widera'); echo $pawel->getName().'<br />'; //Wyświetlone zostanie Pawel echo $ola->getName().'<br />'; //Wyświetlone zostanie Ola Widera $pawel->setSurame('Kowalski'); $ola->setSurame('Rostocka'); echo $pawel->getName().'<br />'; echo $ola->getName().'<br />'; //Wyświetlone zostanie Pawel Kowalski //Wyświetlone zostanie Ola Rostocka Drugi parametr konstruktora posiada domyślną pustą wartość, w przypadku gdy nazwisko osoby nie jest znane w momencie tworzenia obiektu. Za pomocą metody setSurname() można je w późniejszej fazie działania programu ustawić bądź zmienić. Dziedziczenie Dziedziczenie, czyli przekazywanie swoich właściwości i metod klasom potomnym. Stworzoną klasę przykładu Person można rozszerzać o nowe funkcjonalności poprzez dopisywanie nowych metod. Można np. wysłać osobę do pracy przez utworzenie metody work(). Osoba jaką jest również dziecko nie będzie pracować, dziecko za to będzie się uczyć, dla takiej sytuacji dobrym rozwiązaniem jest wykorzystanie właściwości dziedziczenia. Dziecko podobnie jak dorosły posiada imię i nazwisko, natomiast nie chodzi do pracy. Klasa główna, jaką jest Person będzie zawierała wszystkie metody i właściwości wspólne dla wszystkich klas potomnych. Klasy potomne po odziedziczeniu będą zawierały wszystkie metody i właściwości klasy głównej oraz będą mogły posiadać własne metody i właściwości unikalne dla danej klasy. Warto także zapamiętać, że podczas dziedziczenia od klasy głównej wszystkie metody i właściwości publiczne dalej są dostępne wewnątrz klasy potomnej jak i na zewnątrz niej. Natomiast wszystkie metody prywatne w klasie głównej nie są dostępne na zewnątrz klasy jak również wewnątrz klasy potomnej. Aby klasa potomna miała dostęp do wybranych pól z klasy głównej, nawet tych, których nie widać na zewnątrz klasy to w klasie bazowej dla tych pól należy ustawić modyfikator dostępu protected. W PHP 5 każda klasa może dziedziczyć tylko po jednej klasie. Aby dana klasa dziedziczyła po innej klasie należy po nazwie tej klasy dopisać słowo kluczowe extends, po którym podaje się nazwę klasy bazowej, po której klasa potomna ma dziedziczyć. class Person //klasa bazowa { protected $age; //właściwość dostępna również w klasie potomnej private $name; //właściwość dostępna wyłącznie w klasie głównej public function __construct($name ='') { $this->name = $name; } public function setName($name) … public function getName() 3 … } class Child extends Person { private $school; //klasa potomna public function __construct($name = '') { parent::__ construct($name = '') $this->school = 'SP nr 18'; } public function goToPrimarySchool() { echo 'chodzę do szkoły podstawowej '.$this->school; } } $pawel = new Person('Paweł Kowalski'); $ola = new Child('Ola Widera'); echo $pawel->getName().'<br />'; //zostanie wyświetlone: Paweł Kowalski echo $ola->getName().'<br />'; //zostanie wyświetlone: Ola Widera $ola->goToPrimarySchool() //zostanie wyświetlone: chodzę do szkoły podstawowej SP nr 18 Próba wywołania metody goToSchool()na obiekcie klasy Person zgłosi błąd gdyż tylko obiekt klasy Child może chodzić do szkoły. W klasie potomnej konstruktor klasy głównej został przysłonięty przez konstruktor klasy potomnej przez co nie został wykonany. Aby wywołać konstruktor klasy głównej należy użyć słowa kluczowego parent. To samo tyczy się innych metod w klasie potomnej. W wielu zastosowaniach podstawowa klasa bazowa jest na tyle ogólna, że nie powinno się tworzyć obiektu takiej klasy. Aby zapobiec tworzeniu obiektów klas ogólnych wprowadzono w PHP 5 słowo kluczowe abstract. abstract class GeometricalFigure() {…} Aby zmusić klasy potomne do implementacji konkretnej metody wystarczy w klasie głównej utworzyć metodę i poprzedzić ją słowem kluczowym abstract, wtedy klasa potomna (jeśli nie jest klasą abstrakcyjną) musi zaimplementować tą metodę i wypełnić ją ciałem. abstract class GeometricalFigure { abstract public function surfaceArea(); } abstract class Triangle extends GeometricalFigure { private $p; public function surfaceArea($a, $h) { $this->p = $a * $h; echo 'Pole powierzchni trójkąta jest równe '.$this->p; } } 4 Metody oraz właściwości statyczne Właściwości oraz metody klasy mogą być statyczne. Do pól statycznych można się odwoływać bezpośrednio pomijając tworzenie obiektu danej klasy. Aby odwołać się do właściwości statycznej bądź uruchomić metodę statyczną wewnątrz klasy, należy ją poprzedzić słowem kluczowym self, natomiast aby się odwołać to takiej zmiennej lub metody na zewnątrz klasy wtedy należy poprzedzić je nazwą klasy. class ClassName { static public $staticProperty; static public function staticMethod() { echo self::$staticProperty; } } ClassName::staticProperty = 'właściwość statyczna'; ClassName::staticMethod(); Obie linie powyższego kodu spowodują wyświetlenie treści: właściwość statyczna. Właściwości statyczne mogą być wykorzystane do zliczania liczby utworzonych obiektów danej klasy. class Counter { static private $number = 0; public function __construct() { self::$number++; } public function getNumber() { return self::$number; } } $l1 = new Counter(); $l2 = new Counter (); $l3 = new Counter (); echo 'Liczba obiektów: '.$l1->getNumber().'<br />'; $l4 = new Counter (); $l5 = new Counter (); echo 'Liczba obiektów: '.$l1-> getNumber().'<br />' //Liczba obiektów: 3 //Liczba obiektów: 5 Pola statyczne wykorzystywane są we wzorcu projektowym Singleton, który umożliwia utworzenie tylko jednej instancji danej klasy. class Singleton { static private $instance = null; private $text = ''; static public function create() { if (self::$instance == null) { self::$instance = new Singleton(); } return self::$obiekt; } public function setText($text) { 5 $this->text = $text; } public function getText() { return $this->text; } private function __construct() {} private function __clone() {} } $obiekt1 = Singleton::create(); echo 'Obiekt 1: '.$obiekt1->getText().'<br />'; // wyświetlone zostanie: Obiekt 1: $obiekt1->setText('Jestem jedynym obiektem!'); echo 'Obiekt 1: '.$obiekt1->getTekst().'<br />'; // wyświetlone zostanie: Obiekt 1: Jestem jedynym obiektem! $obiekt2 = Singleton::create(); echo 'Obiekt 2: '.$obiekt2->getText().'<br />'; // wyświetlone zostanie: Obiekt 2: Jestem jedynym obiektem! $obiekt2->setText('Ja naprawdę jestem jedynym obiektem!'); echo 'Obiekt 1: '.$obiekt1->getText().'<br />'; // wyświetlone zostanie: Obiekt 1: Jestem naprawdę jestem jedynym obiektem! echo 'Obiekt 2: '.$obiekt2->getText().'<br />'; // wyświetlone zostanie: Obiekt 2: Jestem naprawdę jestem jedynym obiektem! Dzięki temu, że konstruktor i metoda do klonowania obiektu (metoda, która jest domyślnie wywoływana gdy następuje próba klonowania obiektu) jest prywatna to nie można ich użyć do utworzenia nowego obiektu. Jedynym sposobem na utworzenie obiektu tej klasy jest uruchomienie metody statycznej create(), która najpierw sprawdza czy właściwość statyczna $instance zawiera już obiekt klasy Singleton. Jeśli nie zawiera to tworzy ten obiekt i przypisuje go do właściwości $instance. Następnie wartość właściwości $instance czyli utworzony, jedyny obiekt klasy Singleton jest zwracany przez tą metodę statyczną. Interface Podczas projektowania struktury klas przydatne są również interfejsy. Interfejsy reprezentują klasy abstrakcyjne, tzn. zawierają tylko i wyłącznie deklaracje metod oraz właściwości. W interfejsie nie można używać modyfikatorów dostępu gdyż wszystkie pola muszą być publiczne. Aby utworzyć interfejs należy użyć słowa kluczowego interface, po którym następuje nazwa interfejsu. interface ExemplaryInterface { $property; function method1(); function method2(); } Interfejs może dziedziczyć wyłącznie od innych interfejsów. Ilość dziedziczonych interfejsów jest nieograniczona. Aby dziedziczyć od innego interfejsu to po nazwie interfejsu potomnego wystarczy dopisać słowo kluczowe extends, po którym podaje się listę nazw innych interfejsów separując je przecinkiem. 6 interface ChildInterface extends ExemplaryInterface, OtherInterface { function childMethod(); } Klasy mogą implementować interfejsy w nieograniczonej liczbie. Implementacja interfejsu polega na tym, że klasa, która implementuje dany interfejs musi posiadać metody i właściwości publiczne określone w implementowanym interfejsie. Interfejsy, które implementuje klasa określa się poprzez dodanie po nazwie klasy słowa kluczowego implements, po którym podaje się listę nazw implementowanych interfejsów separując je przecinkiem. class ExemplaryClass implements ExemplaryInterface { public $property; public function method1() { //... } public function method2() { //... } } Jeśli klasy implementują ten sam interfejs, oznacza to, że posiadają wszystkie metody i właściwości zadeklarowane w danym interfejsie. 7