obiektowka PHP, Programowanie


Staramy się po prostu za pomocą klas opisać modelowana rzeczywistość. Modelowanie rozpoczynamy od obiektów najbardziej ogólnych, powoli je uszczegóławiając.

Załóżmy, ze chcemy zaprogramować lampkę nocną oraz lampę ogrodową, która włącza się po zmroku za sprawą czujnika ruchu. Można do problemu podejść na skróty i napisać od razu dwie klasy opisujące odpowiednie lampy. My jednak problem potraktujemy oddzielnie (utrudnimy sobie tym samym w przyszłości możliwość tworzenia kolejnych lamp). Co więcej, lampy te nie będą miały ze sobą nic wspólnego (co również nie będzie dobrym posunięciem). Zastanówmy się jakie cechy wspólne maja obie lampy:

Stworzymy wiec ogólną klasę bazową Lampa.

Klasa ta będzie zawierała metody (funkcje wchodzące w skład klasy): zapal() oraz zgas(). Dodatkowo klasa ta będzie zawierała pole (odpowiednik zmiennej globalnej, dostępnej jednak bezpośrednio z poziomu metod klasy) odpowiadające żarówce (po zapoznaniu się z projektem lamp zastanówmy się nad podobnym projektem dla różnych żarówek: zwykłej, jarzeniowej, halogenowej i itp.).

Klasy LampkaNocna oraz LampaOgrodowa będą dziedziczyły po klasie Lampa, co oznacza, ze będą miały wszystkie jej cechy, rozszerzając je jednocześnie o cechy charakterystyczne dla nich samych. Co więcej, każda lampka dziedzicząca po klasie Lampa będzie typu Lampa.

Klasa LampkaNocna zawiera dodatkowe metody rozjasnij() oraz sciemnij(). Lampa ogrodowa zaś na pierwszy rzut oka niczym się nie różni od klasy, po której dziedziczy, jednak ma dodatkowe pole czujnikRuchu, będące obiektem innej klasy - klasy zarządzającej czujnikiem ruchu w ogrodzie.

Dziedziczymy wówczas, gdy dana klasa jest typu klasy, po której dziedziczymy - lampka nocna jest rodzajem lampy, również lampa ogrodowa jest rodzajem lampy. Jeśli chcemy zaznaczyć, ze dany obiekt korzysta z innego obiektu, bądź inny obiekt wchodzi w jego skład, użyjemy kompozycji, np. żarówka czy pole czujnikRuchu lampy ogrodowej.

Zapisujemy to w PHP

Klasy w PHP maja następującą postać:

[-]

 

PHP

1. class NazwaKlasy {

2.  [public|protected|private] $pole;

3.  //inne pola...

4.  [public|protected|provate] function nazwaMetody($parametry,...) {

5.  }

6.  //inne metody...

7. }

Listing zwinięty - 7 linii

A tak może wyglądać klasa Lampa:

[-]

 

 

PHP

1. class Lampa {

2.  protected $zarowka;

3.  public function _construct (Zarowka $zarowka) {

4.    echo 'Wkrecam .arówke<br>';

5.    $this->zarowka = $zarowka;

6.  }

7.  public function zapal() {

8.    $this->zarowka->zapal();

9.    echo 'Lampka zapalona<br>';

10.  }

11.  public function zgas() {

12.    $this->zarowka->zgas();

13.    echo 'Lampka zgaszona<br>';

14.  }

15. }

Listing zwinięty - 15 linii

Wygląda to zupełnie inaczej niż kod, z którym mieliśmy do czynienia do tej pory. Przeanalizujmy go dokładnie.

Definiujemy klasę o nazwie Lampa, która ma pole $zarowka, będące zmienna przechowującą obiekt żarówki danej lampki, oraz trzy metody: _construct(), zapal() oraz zgas().

Same funkcje wyglądają podobnie do tych już znanych. Nowe jest jednak słowo public przed każda z nich, które oznacza, ze funkcja ta może być wywoływana przez każdego. Zamiast niego, można użyć słów:

Słów kluczowych public/protected/private używa się także w odniesieniu do pól (pole $zarówka jest chronione (protected), jest wiec dostępne jedynie z poziomu klasy Lampa oraz klas po niej dziedziczących).

Wiemy do czego służą metody zapal() oraz zgas(). Czym jednak jest metoda _construct()? Ma ona dziwna nazwę i kod, który wykonuje, tez jest inny od już znanych.

Metoda _construct() jest tak zwanym konstruktorem, czyli metoda wykonywana zawsze podczas tworzenia obiektu, jeszcze przed wykonaniem jakiejkolwiek innej metody. Nasz konstruktor ma za zadanie przypisanie do pola $zarówka obiektu przekazanego w parametrze (przed nazwa parametru umieszczono słowo Żarówka - jest to nazwa typu klasy, której zmienna musi być przekazana jako parametr konstruktora (jeśli spróbujemy przekazać cokolwiek innego niż obiekt klasy Żarówka, PHP zwróci błąd):

 

 

PHP

$this->zarowka = $zarowka;

Nie podajemy tu zwykłej nazwy zmiennej, która została użyta podczas definiowania pola, a poprzedzamy ją słowem $this (po polsku: to, ten), które określa, ze odnosimy się do pola aktualnej klasy. Podobnie zrobimy w przypadku, gdy z poziomu którejś z metod klasy chcemy wywołać inna z jej metod, np.: [-]

 

 

PHP

1. public function test() {

2.  $this->zapal();

3. }

Do tworzenia obiektów klasy używa się słowa kluczowego new. Służy ono do tworzenia instancji obiektu. Tak wiec:

 

PHP

$zarowka = new Zarowka();

tworzy nowy obiekt klasy Żarówka, zaś:

 

PHP

$lampa = new Lampa($zarowka);

tworzy obiekt Lampa i przekazuje do konstruktora wcześniej utworzony obiekt klasy Żarówka. Przyjrzymy się teraz metodzie zapal:

[-]

 

 

PHP

1. public function zapal() {

2.  echo 'Lampka zapalona<br>';

3.  $this->zarowka->zapal();

4. }

Listing zwinięty - 4 linii

Poza wyświetleniem napisu ma ona za zadanie zapalenie żarówki wchodzącej w skład lampki. W tym celu pobieramy obiekt przechowywany w polu $zarówka:

 

PHP

$this->zarowka

a następnie wywołujemy jego metodę zapal (a wiec metodę wchodząca w skład klasy Żarówka):

 

PHP

$this->zarowka->zapal();

Analogicznie działa metoda zgaś. Pamiętajmy wiec, że projektowane klasy Żarówka powinny zawierać metody zapal oraz zgaś.

Teraz można utworzyć obiekt klasy Lampa i przetestować go. Poza klasą wpiszemy:

[-]

 

 

PHP

1. $zarowka = new Zarowka();

2. $lampka = new Lampa($zarowka);

3. $lampka->zapal();

4. $lampka->zgas();

Listing zwinięty - 4 linii

Nasza klasa Lampa nie definiuje jednak żadnego konkretnego rodzaju lampy, nie powinno być więc możliwości utworzenia jej obiektu. Dodajmy przed słowem kluczowym class dodatkowe słówko abstract. Spowoduje to uczynienie z klasy Lampa klasy abstrakcyjnej.

Ważne jest, że nie da się utworzyć obiektów klas abstrakcyjnych, można po nich jedynie dziedziczyć. Co więcej, w klasach abstrakcyjnych można definiować metody abstrakcyjne. Metoda abstrakcyjna jest swojego rodzaju zapowiedzią metody, której ciało ma zostać zdefiniowane w klasach dziedziczących. Metoda abstrakcyjna zawiera jedynie nazwę i określoną listę parametrów, np.:

[-]

 

 

PHP

1. abstract public function zapal();

2. abstract public function zgas();

Listing zwinięty - 2 linii

Nie zawiera zaś kodu w nawiasach klamrowych. Metod abstrakcyjnych używa się wówczas, gdy nie da się z góry określić sposobu ich działania, wiadomo jednak, ze muszą one wystąpić w każdej z klas dziedziczących po klasie abstrakcyjnej. Jeśli klasa dziedziczącą nie dostarczy ciała dla wszystkich metod abstrakcyjnych klasy po której dziedziczy, sama także staje się abstrakcyjna. Klasa LampkaNocna będzie dziedziczyła po klasie Lampa, będzie więc zawierała wszystkie jej cechy oraz dodatkowo możliwość ściemniania i rozjaśniania światła:

[-]

 

 

PHP

1. class LampkaNocna extends Lampa {

2.  private $sciemniaczZarowki;

3.  public function _construct (Zarowka $zarowka) {

4.    parent::_construct($zarowka);

5.    $this->sciemniaczZarowki = new SciemniaczZarowki($this->zarowka);

6.  }

7.  public function rozjasnij() {

8.    $this->sciemniaczZarowki-> rozjasnij();

9.  }

10.  public function sciemnij() {

11.    $this->sciemniaczZarowki-> sciemnij();

12.  }

13. }

Listing zwinięty - 13 linii

Klasa ta zawiera więcej metod oraz korzysta z dodatkowej klasy SciemniaczZarowki, która ma za zadanie odpowiednio sterować jasnością światła wkręconej w nią żarówki. Zauważmy, że konstruktor jest tu nieco inny. Wywołanie:

 

PHP

parent::_construct($zarowka);

powoduje uruchomienie konstruktora klasy, po której nasza nowa klasa dziedziczy (parent - ang. rodzic), a wiec konstruktora klasy Lampa. Następnie tworzony jest obiekt klasy SciemniaczZarowki, do której konstruktora przekazywany jest obiekt żarówki, która klasa ściemniacza ma sterować:

 

PHP

$this->sciemniaczZarowki = new SciemniaczZarowki($this->zarowka);

Jak widać, mimo ze w klasie LampkaNocna nie zostało zdefiniowane pole $zarowka, klasa ta ma dostęp do pola o tej nazwie z klasy, po której dziedziczy, gdyż w klasie Lampa pole to zostało ustalone jako chronione (protected).

Klasa ściemniacza może wyglądać tak: [-]

 

 

PHP

1. class SciemniaczZarowki {

2.  private $zarowka;

3.  private $poziomJasnosci = 100;

4.  public function _construct (Zarowka $zarowka) {

5.    $this->zarowka = $zarowka;

6.  }

7.  public function rozjasnij() {

8.    if ($this->poziomJasnosci < 100) {

9.      $this->poziomJasnosci++;

10.      echo 'Rozjasniam swiatlo zarowki<br>';

11.    }

12.  }

13.  public function sciemnij() {

14.    if ($this->poziomJasnosci > 1) {

15.      $this->poziomJasnosci--;

16.      echo 'Przyciemniam swiatlo zarowki<br>';

17.    }

18.  }

19. }

Listing zwinięty - 19 linii

Pole $zarowka nie jest tu używane, gdyż sposób rozjaśniania i ściemniania żarówki zależy od tego w jaki sposób rozwiążemy projekt klas żarówek. A oto kod testujący lampkę nocna:

[-]

 

 

PHP

1. $zarowka = new Zarowka();

2. $lampka = new LampkaNocna($zarowka);

3. $lampka->zapal();

4. $lampka->rozjasnij();

5. $lampka->sciemnij();

6. $lampka->sciemnij();

7. $lampka->rozjasnij();

8. $lampka->rozjasnij();

9. $lampka->rozjasnij();

10. $lampka->zgas();

Listing zwinięty - 10 linii

Mimo ze klasa LampkaNocna nie ma zdefiniowanych metod zapal() i zgas(), zostają wywołane odpowiednie metody klasy Lampa. Klasa LampaOgrodowa jest jeszcze prostsza:

[-]

 

 

PHP

1. class LampaOgrodowa extends Lampa {

2.  private $czujnikRuchu;

3.  public function _construct (Zarowka $zarowka) {

4.    parent::_construct($zarowka);

5.    $this-> czujnikRuchu = new CzujnikRuchu($this->zarowka);

6.  }

7. }

Listing zwinięty - 7 linii

Korzysta dodatkowo z klasy CzujnikRuchu: [-]

 

 

PHP

1. class CzujnikRuchy {

2.  private $zarowka;

3.  public _construct(Zarowka $zarowka) {

4.    $this->zarowka = $zarowka;

5.  }

6.  public function uruchom() {

7.    echo 'Czujnik ruchu uruchomiony<br>';

8.    //wykrywanie ruchy...

9.  }

10.  private function wykrytoRuch() {

11.    echo 'Wykryto ruch<br>';

12.    $this->zarowka->wlacz();

13.  }

14.  private function ruchZanikl() {

15.    echo 'Ruch zanikl<br>';

16.    $this->zarowka->wylacz();

17.  }

18. }

Listing zwinięty - 18 linii

Klasy LampkaNocna i LampaOgrodowa są typu Lampa i każda metoda bądź kod potrafiący operować klasa Lampa, potrafi operować także naszymi klasami lamp:

[-]

 

 

PHP

1. function test(Lampa $lampa) {

2.  $lampa->zapal();

3.  $lampa->zgas();

4. }

5. $zarowka = new Zarowka();

6. $lampkaNocna = new LampkaNocna ($zarowka);

7. test($lampkaNocna);

Listing zwinięty - 7 linii

Funkcja test oczekuje jako parametr obiektu klasy Lampa i bez błędu przyjmuje tutaj obiekt klasy LampkaNocna. Dzieje się tak dzięki dziedziczeniu. Klasy dziedzicząc po innej klasie stają się typu klasy, po której dziedziczą.

I po co to wszystko?

Programowanie obiektowe to dziś codzienność. W ten właśnie sposób buduje się dziś zdecydowana większość programów. I to niezależnie od języka - czy to PHP, C++, Java, Python czy zdobywający popularność Ruby, programowanie obiektowe jest podstawa.

Od wersji 5 w PHP wprowadzono wiele udogodnień w zakresie programowania obiektowego. Dodano także nowe biblioteki, pozwalające wykorzystać potencjał drzemiący w obiektach.



Wyszukiwarka

Podobne podstrony:
obiektowka PHP 2, Programowanie
PHP profesjonalnie programowanie obiektowe i narzędzia programisty 08 2006
PHP Programowanie obiektowe phppro
Programowanie obiektowe w PHP 5
PL PHP programowanie obiektowe
PHP Programowanie obiektowe
PHP Programowanie obiektowe phppro
PHP Programowanie obiektowe
PHP Programowanie obiektowe phppro
informatyka programowanie obiektowe w php 5 hasin hayder ebook

więcej podobnych podstron