53
PHP programowanie obiektowe Wprowadzenie do OOP w PHP 2013-01-21 Uazz.pl

Php programowanie obiektowe

Embed Size (px)

DESCRIPTION

PHP wstęp do programowania obiektowego.

Citation preview

PHP programowanie obiektowe Wprowadzenie do OOP w PHP 2013-01-21

Uazz.pl

Uazz.pl Strona 2

Uazz.pl Strona 3

Zawartość PHP programowanie obiektowe ............................................................................. 1

PHP programowanie obiektowe ............................................................................. 4

Obiekty ............................................................................................................................... 5

Atrybuty obiektu .......................................................................................................... 7

Metody................................................................................................................................ 9

Modyfikatory dostępu ............................................................................................. 11

Metoda przeciążania ................................................................................................ 14

Konstruktor ................................................................................................................... 16

Stałe w klasie ............................................................................................................... 19

Słowo kluczowe instanceof ................................................................................. 20

Metoda __toString() ................................................................................................ 22

Dziedziczenie ............................................................................................................... 24

Klasy abstrakcyjne i metody .............................................................................. 28

Interfejsy ....................................................................................................................... 31

Polimorfizm ................................................................................................................... 36

Programowanie obiektowe II ................................................................................ 38

Słowa kluczowe static ............................................................................................ 38

Słowo kluczowe final ............................................................................................... 40

Deep copy vs shallow copy .................................................................................. 42

Wyjątki ............................................................................................................................. 47

Konstruktor przeciążenia ..................................................................................... 50

Uazz.pl Strona 4

PHP programowanie obiektowe

W tej części kursu PHP będziemy mówić o obiektowym programowaniu w PHP.

Istnieją trzy powszechnie stosowane paradygmaty programowania. Programowanie

proceduralne, programowanie funkcjonalne i programowanie obiektowe. PHP 5

obsługuje zarówno proceduralne, jak i obiektowe programowanie. We wcześniejszych

wersjach PHP miał ograniczone wsparcie lub był brak wsparcia dla OOP.

Programowanie obiektowe (OOP) jest paradygmatem programowania, który używa

obiektów i ich interakcje do projektowania aplikacji i programów komputerowych.

(Wikipedia)

Istnieją pewne podstawowe pojęcia programowania w OOP:

Abstraction (Abstrakcja)

Polymorphism (Polimorfizm)

Encapsulation (Hermetyzacja)

Inheritance (Dziedziczenie)

Abstrakcja jest to uproszczenie złożonej rzeczywistości przez modelowanie klas

odpowiednich do problemu. Polimorfizm jest to proces, który używa operatora lub

funkcji w różny sposób dla różnych danych wejściowych. Hermetyzacja ukrywa

szczegóły dotyczące implementacji klasy z innych obiektów. Dziedziczenie jest to

sposób, aby nowe klasy używały klas, które już zostały zdefiniowane.

Uazz.pl Strona 5

Obiekty

Obiekty są podstawowym budulcem programu OOP w PHP. Obiekt jest to połączenie

danych i metod. W programie OOP możemy tworzyć obiekty. Obiekty te komunikują

się ze sobą za pomocą metod. Każdy obiekt może odbierać wiadomości, wysyłać

wiadomości i przetwarzać dane.

Istnieją dwa kroki w tworzeniu obiektu. Po pierwsze musimy utworzyć klasę. Klasa

jest szablonem dla obiektu. Jest to plan, który opisuje stan i zachowanie obiektów

klasy. Klasa może służyć do tworzenia wielu obiektów. Obiekty utworzone w czasie

wykonywania z klasy są nazywane instances (wystąpienia) danej klasy.

<?php

class Przyklad {}

$object = new Przyklad();

print_r($object);

echo gettype($object), "\n";

?>

W pierwszym przykładzie tworzymy prosty obiekt.

class Przyklad {}

To jest definicja prostej klasy. Zawartość szablonu jest pusta. Nie ma żadnych danych

ani metody.

$object = new Przyklad();

Tworzymy nową instancję klasy Przyklad. W tym celu uzywamy słowo kluczowe new.

Zmienna $object jest uchwytem do utworzonego obiektu.

print_r($object);

echo gettype($object), "\n";

Za pomocą funkcji print_r() uzyskujemy informacje na temat obiektu i funkcji

gettype(), aby uzyskać typ zmiennej.

$ php klasa.php

Przyklad Object

(

Uazz.pl Strona 6

)

object

Nie mamy tu wiele informacji, ponieważ definicja klasy była pusta. Typ zmiennej to

object.

Uazz.pl Strona 7

Atrybuty obiektu

Atrybuty obiektu to dane w instancji klasy. Atrybutami obiektu nazywane są zmienne

instancji lub pola. Zmienną instancji jest zmienna zdefiniowana w klasie, dla której

każdy obiekt w klasie ma osobną kopię.

<?php

class Osoba {

public $imie = "";

}

$p1 = new Osoba();

$p1->imie = "Janek";

$p2 = new Osoba();

$p2->imie = "Beata";

echo $p1->imie . "\n";

echo $p2->imie . "\n";

?>

W powyższym skrypcie PHP mamy klasę Osoba z jednym polem (zmienną).

$p1 = new Osoba();

$p1->imie = "Janek";

Tworzymy instancję klasy Osoba. I zestaw zmiennej $imie z wartością "Janek".

Używamy -> operatora, aby uzyskać dostęp do atrybutów obiektów.

$p2 = new Osoba();

$p2->imie = "Beata";

Tworzymy inne wystąpienie klasy Osoba. Tu możemy sobie ustawić zmienną "Beata".

echo $p1->imie . "\n";

echo $p2->imie . "\n";

Możemy wyświetlić zawartość zmiennych na konsoli.

$ php osoba.php

Janek

Beata

Uazz.pl Strona 8

Widzimy, dane wyjściowe skryptu. Każde wystąpienie klasy Osoba ma osobną kopię

zmiennej $imie.

Uazz.pl Strona 9

Metody

Metody są zdefiniowane w ciele klasy. Służą one do wykonywania operacji z

atrybutami naszych obiektów. Metody są istotne w koncepcji enkapsulacji

(hermetyzacji) paradygmatu OOP. Na przykład możemy mieć metodę connect() w

naszej klasie AccessDatabase. Nie musimy być informowani, jak dokładnie metoda

connect() łączy się z bazą danych. Wiemy tylko, że jest używana do łączenia się z bazą

danych. Jest to istotne w podziale obowiązków w programowaniu. Zwłaszcza w

dużych aplikacjach.

<?php

class Kolo {

public $promien;

function setRadius($promien) {

$this->promien = $promien;

}

function powierzchnia() {

return $this->promien * $this->promien * M_PI;

}

}

$c = new Kolo();

$c->setRadius(5);

echo $c->powierzchnia(), "\n";

?>

W przykładzie powyżej mamy klasę Kolo. Możemy zdefiniować dwie metody.

public $promien;

Mamy jedną zmienną (pole). Jest to promień okręgu. Słowo kluczowe public jest

specyfikatorem dostępu. Mówi, że zmienna jest w pełni dostępna z zewnątrz.

function setRadius($promien) {

$this->promien = $promien;

}

Jest to metoda setRadius(). Jest to normalna funkcja PHP. Tak nazywamy funkcje

zdefiniowane wewnątrz metody klasy. Zmienna $this jest to specjalna zmienna,

której używamy, aby odwołać się do zmiennej.

Uazz.pl Strona 10

function area() {

return $this->promien * $this->promien * M_PI;

}

Metoda powierzchnia() zwraca powierzchnię koła. M_PI jest to stała wbudowana w

języku PHP.

$ php kolo.php

78.5398163397

Uruchomiony przykład.

Uazz.pl Strona 11

Modyfikatory dostępu

Modyfikatory dostępu ustawiają widoczność pól i metod. PHP 5 ma trzy rodzaje

modyfikatorów dostępu. Public (publiczny), private( prywatne) i protected

(chronione). Do public (publicznych) modyfikatorów można uzyskać dostęp z

dowolnego miejsca. Elementy protected mogą być dostępne tylko w obrębie samej

klasy i w klasach dziedziczonych i klasach rodziców. Elementy private (prywatne)

mogą być dostępne tylko w klasie, która definiuje element prywatny.

Modyfikatory dostępu służą do ochrony danych przed przypadkowymi zmianami.

Czyni to programy bardziej odporne na błędy.

<?php

class Osoba {

public $imie = "";

private $wiek;

}

$p = new Osoba();

$p->imie = "Janek";

#$p->wiek = 17;

echo $p->imie . "\n";

?>

W powyższy skrypcie PHP mamy dwie zmienne (pola). Jedna jest zadeklarowana jako

public (publiczna), a druga jako private (prywatna).

$p->imie = "Jane";

#$p->wiek = 17;

Mamy dostęp do zmiennej $imie z zewnątrz klasy. Przez zewnętrzny dostęp mamy na

myśli "nie w klasie". Wszystko jest OK, dopóki zmienna $imie jest zadeklarowana

jako publiczna (public). Dostęp do zmiennej $wiek nie jest możliwy. Prywatny

(private) modyfikator zabrania tego. Jeśli odkomentujemy linię kodu, będzie

wyświetlony komunikat 'Fatal error: Cannot access private property Person::$age'

error.

"błąd krytyczny: nie ma dostępu do właściwości prywatnej Osoba:: $wiek' błąd.

Uazz.pl Strona 12

<?php

class Baza {

public $imie = "Baza";

protected $id = 6344;

private $is_defined = "tak";

}

class Rozszerzona extends Baza {

public function info() {

echo "To jest klasa Rozszerzona\n";

echo "Klasa dziedziczy: \n";

echo $this->imie . "\n";

echo $this->id . "\n";

echo $this->is_defined . "\n";

}

}

$informacja = new Rozszerzona();

$informacja->info();

?>

W tym skrypcie PHP mamy pochodne klasy, która rozszerza klasę bazową. Klasa

bazowa ma trzy pola. Wszystkie z innym modyfikatorem dostępu. Pole $is_defined

nie jest dziedziczone. Prywatny (private) modyfikator zapobiega temu.

public function info() {

Metoda info() ma publiczny (public) modyfikator dostępu. Oznacza to, może ona

zostać wywołana poza środowiskiem klasy.

$ php dostep.php

To jest klasa Rozszerzona

Klasa dziedziczy:

Baza

6344

$

Uruchomiając skrypt PHP, możemy otrzymać następujące wyniki. Pola publiczne i

chronione są dziedziczone, prywatne pole nie jest.

Uazz.pl Strona 13

<?php

class SysInfo {

private function get_date() {

return date("Y/m/d");

}

private function get_version() {

return phpversion();

}

public function getInfo() {

$date = $this->get_date();

$wersja = $this->get_version();

echo "Data: $date\n";

echo "Wersja PHP to: $wersja\n";

}

}

$sys = new SysInfo();

$sys->getInfo();

#$sys->get_date();

?>

W tym skrypcie PHP mamy klasę SysInfo. Wynikiem działania są informacje o

systemie wyświetlane w konsoli. Mamy dwie funkcje prywatne i jedną publiczną.

Metody prywatne są tu tylko używane wewnątrz klasy SysInfo. Nie są one

przeznaczone do używania poza klasą.

$sys = new SysInfo();

$sys->getInfo();

#$sys->get_date();

Tworzymy instancję klasy SysInfo i wywołujemy dostępną metodę publiczną

getInfo(). Metoda getInfo() używa wewnętrznie prywatnych metod do jej pracy.

Odkomentowanie ostatniego wiersza kodu daje błąd.

Uazz.pl Strona 14

Metoda przeciążania

Metoda przeciążenia pozwala na tworzenie kilku metod o tej samej nazwie, które

różnią się od siebie typem danych wejściowych.

Czy przeciążanie metody jest dobre? Biblioteka Qt4 daje dobry przykład dla

użytkownika. Klasa QPainter ma trzy metody, aby narysować prostokąt. Ich nazwa to

drawRect(), a ich parametry różnią się. Jedna z nich ma odniesienie do obiektu

prostokąt typu float, inna ma odniesienie do obiektu rectangle typu int i ostatnia ma

cztery parametry, x, y, szerokość, wysokość. Jeśli język C++ jest językiem, w którym

Qt jest rozwijany, nie ma metod przeciążania, twórcy biblioteki będą musieli utworzyć

metody, takie jak drawRectRectF(), drawRectRect(), drawRectXYWH(). Rozwiązanie

z przeciążeniem metody jest bardziej eleganckie.

<?php

class Suma {

public function getSum() {

return 0;

}

public function getSum($x) {

return $x;

}

public function getSum($x, $y) {

return $x + $y;

}

}

$s = new Suma();

echo $s->getSum() . "\n" ;

echo $s->getSum(5) . "\n" ;

echo $s->getSum(3, 4) . "\n" ;

?>

Jest to metoda przeciążania, znamy to z języków, takich jak C#, Java lub C++. Ale to

nie działa w PHP. Po uruchomieniu tego przykładu, otrzymujemy następujący

komunikat o błędzie: 'Fatal error: Cannot redeclare Sum::getSum()' "błąd krytyczny:

nie można zadeklarować Suma::getSum()'. Funkcje PHP mogą przyjmować dowolną

liczbę zmiennych domyślnie.

Do symulacji, metody przeciążenia w PHP, możemy użyć funkcji func_get_args().

Uazz.pl Strona 15

<?php

class Suma {

public function getSum() {

$args = func_get_args();

if (empty($args)) return 0;

foreach ($args as $arg) {

$sum += $arg;

}

return $sum;

}

}

$s = new Suma();

echo $s->getSum() . "<br />" ;

echo $s->getSum(5) . "<br />" ;

echo $s->getSum(3, 4) . "<br />" ;

echo $s->getSum(3, 4, 7) . "<br />" ;

?>

Tym razem, skrypt zostanie uruchomiony.

$args = func_get_args();

Funkcja func_get_args() zwraca tablicę, obejmującą listę argumentów funkcji.

foreach ($args as $arg) {

$sum += $arg;

}

Przechodzimy przez wszystkie elementy tablicy, a następnie obliczamy sumę.

echo $s->getSum() . "\n" ;

echo $s->getSum(5) . "\n" ;

echo $s->getSum(3, 4) . "\n" ;

echo $s->getSum(3, 4, 7) . "\n" ;

Wywołujemy taką samą nazwę metody z różną liczbą wejść.

Uazz.pl Strona 16

Konstruktor

Konstruktor jest specjalnym rodzajem metody. Jest ona automatycznie wywoływana,

gdy tworzony jest obiekt. Celem konstruktora jest inicjowanie stanu obiektu. Nazwa

konstruktora w PHP 5 jest zawsze __construct(). (podwójne podkreślenie)

<?php

class Piosenka {

function __construct() {

echo "Obiekt Piosenka został utworzony \n";

}

}

$piosenka = new Piosenka();

?>

Mamy klasę Piosenka. Ta klasa posiada konstruktor, który wyświetla wiadomość na

konsoli.

$piosenka = new Piosenka();

Jest to czas, kiedy obiekt jest tworzony i konstruktor jest wywoływany. Dostajemy

wiadomość na konsoli.

$ php konstruktor.php

Obiekt Piosenka został utworzony

Jest to wynik działania skryptu.

Konstruktory często używają argumentów.

<?php

class Piosenka {

function __construct($piosenka) {

echo "Piosenka $piosenka jest utworzona \n";

}

}

Uazz.pl Strona 17

$piosenka = new Piosenka("Malinowy król");

?>

Możemy zmienić nieco poprzedni przykład. Możemy przekazać wartość do

konstruktora.

function __construct($piosenka) {

echo "Piosenka $piosenka jest utworzona \n";

}

Przekazany argument jest przechowywany w zmiennej lokalnej $piosenka.

$ php konstruktor2.php

Piosenka Malinowy król jest utworzona

Teraz mamy wyświetlony tytułu piosenki w konsoli.

W następnym przykładzie możemy zainicjować pola klasy. Inicjacja zmiennych jest

typowym zadaniem dla konstruktorów.

<?php

class Przyjaciel {

private $urodzony;

private $imie;

function __construct($imie, $urodzony) {

$this->imie = $imie;

$this->urodzony = $urodzony;

}

function getInfo() {

echo "Mój przyjaciel $this->imie urodził się w $this->urodzony\n";

}

}

$przyjaciel = new Przyjaciel("Adam", 1976);

$przyjaciel->getInfo();

?>

Mamy klasę Przyjaciel z polami i metodami.

private $urodzony;

private $imie;

Uazz.pl Strona 18

Mamy dwie zmienne w definicji klasy. Słowo kluczowe private jest modyfikatorem

dostępu. Jest to forma hermetyzacji. Słowo kluczowe private jest najbardziej

restrykcyjnym modyfikatorem. Pozwala na dostęp tylko obiektowi, w którym

występuje. Więcej na ten temat później.

function __construct($imie, $urodzony) {

$this->imie = $imie;

$this->urodzony = $urodzony;

}

W konstruktorze inicjujemy dwa pola. Zmienna $this jest używana do dostępu do

zmiennych obiektu.

$przyjaciel = new Przyjaciel("Adam", 1976);

$przyjaciel->getInfo();

Tworzymy obiekt Przyjaciel z dwoma argumentami. Następnie możemy wywołać

metodę getInfo() obiektu. Do wywołania metody obiektu, możemy użyć operatora -

>.

$ php przyjaciel.php

Mój przyjaciel Adam urodził się w 1976

Uazz.pl Strona 19

Stałe w klasie

PHP umożliwia tworzenie stałych klasy. Te stałe nie należą do konkretnego obiektu.

Należą one do tej klasy. Umownie stałe są pisane wielkimi literami.

<?php

class Math {

const PI = 3.14159265359;

public function getPI() {

echo self::PI;

}

}

$math = new Math();

echo Math::PI, "\n";

echo $math->getPI(), "\n";

?>

Mamy klasy Math ze stałą PI.

const PI = 3.14159265359;

Słowo kluczowe const jest używane do definiowania stałych.

public function getPI() {

echo self::PI;

}

Stałe w klasie są dostępne w ramach metody za pomocą słowa kluczowego self, a

następnie przez dwa dwukropki.

echo Math::PI, "\n";

echo $math->getPI(), "\n";

Wyświetlamy stałą PI na konsoli. W pierwszym przypadku mamy stałą wartość

odwołując się do nazwy klasy, a następnie dwa dwukropki i nazwę stałej. Należy

zauważyć, że obiekt nie był potrzebny, aby uzyskać dostęp do stałej. W drugim

przypadku używamy metody obiektu.

Uazz.pl Strona 20

Słowo kluczowe instanceof

Słowo kluczowe instanceof jest używane do określenia czy dany obiekt jest obiektem

danej klasy, lub klasy, która dziedziczy po danej klasie, oraz czy zmienna PHP jest

instancją obiektu pewnej klasy.

<?php

class Kot {}

class Pies {}

class Ptak {}

$objekt = array(new Kot(), new Pies(), new Kot(),

new Ptak(), new Ptak(), new Pies(),

new Pies(), new Kot(), new Ptak()

);

shuffle($objekt);

foreach ($objekt as $object) {

if ($object instanceof Kot) {

echo "To jest Kot <br />";

} elseif ($object instanceof Pies) {

echo "To jest Pies <br />";

} elseif ($object instanceof Ptak) {

echo "To jest Ptak <br />";

}

}

?>

W skrypcie powyżej mamy trzy klasy. Kot, Pies i Ptak. Przechodzimy przez tablicę i

wyświetlamy nazwy klas dla każdej wartości tablicy.

$objekt = array(new Kot(), new Pies(), new Kot(),

new Ptak(), new Ptak(), new Pies(),

new Pies(), new Kot(), new Ptak()

);

Tworzymy tablicę tych obiektów.

shuffle($objekt);

Uazz.pl Strona 21

Funkcja shuffle losuje kolejność elementów w tablicy. W tym momencie nie wiemy,

jakie klasy są zapisane w tablicy.

if ($object instanceof Kot) {

echo "To jest Kot <br />";

}

Tutaj możemy użyć słowa kluczowego instanceof aby dowiedzieć się, jaki jest typ

klasy.

$ php instanceof.php

To jest Ptak

To jest Kot

To jest Kot

To jest Pies

To jest Pies

To jest Kot

To jest Pies

To jest Ptak

To jest Ptak

Dane wyjściowe uruchomionego skryptu.

Uazz.pl Strona 22

Metoda __toString()

Gdy używamy słowa kluczowego print lub echo występującego z instancją obiektu,

to wywoływana jest specjalna metoda __toString(). Pokażemy to w poniższym

przykładzie.

<?php

class Kot {

public $imie;

public $wiek;

function __construct($imie, $wiek) {

$this->wiek = $wiek;

$this->imie = $imie;

}

function __toString() {

return "Kot: $this->imie, Wiek: $this->wiek \n";

}

}

$pimpek = new Kot("Pimpek", 6);

$tofik = new Kot("Tofik", 4);

print $pimpek;

echo $tofik;

?>

Mamy klasę Kot z zdefiniowaną specjalną metodą __toString().

function __toString() {

return "Kot: $this->imie, Wiek: $this->wiek \n";

}

Metoda wyświetla podstawowe informacje o obiekcie.

$pimpek = new Kot("Pimpek", 6);

$tofik = new Kot("Tofik", 4);

Uazz.pl Strona 23

Tworzymy dwa obiekty klasy Kot.

print $pimpek;

echo $tofik;

I używamy słów kluczowych print lub echo.

$ php tostring.php

Kot: Pimpek, Wiek: 6

Kot: Tofik, Wiek: 4

Powyżej wynik działania skryptu.

Uazz.pl Strona 24

Dziedziczenie

Dziedziczenie jest to sposób, aby nowe klasy były tworzone przy użyciu klas, które już

zostały zdefiniowane. Nowo powstałe klasy są nazywane klasami pochodnymi, tak

nazywane są klasy, które tworzymy na podstawie klasy bazowej. Ważne, jest, że

korzyści wynikające z dziedziczenia to wielokrotne wykorzystanie kodu i zmniejszenie

złożoności programu. Klasy pochodne (potomkowie) mogą zastąpić lub rozszerzyć

funkcjonalność klasy bazowej (przodków).

<?php

class Podstawowa {

function __construct() {

echo " Konstrukcja klasy podstawowej \n";

}

}

class Pochodna extends Podstawowa {

function __construct() {

parent::__construct();

echo " Konstrukcja klasy pochodnej \n";

}

}

$obj1 = new Podstawowa();

$obj2 = new Pochodna();

?>

W tym skrypcie PHP mamy dwie klasy. I klasę pochodną i klasę podstawową. Klasa

Pochodna dziedziczy z klasy Podstawowa.

class Pochodna extends Podstawowa {

W PHP, używamy słowa kluczowego extends do tworzenia relacji dziedziczenia.

function __construct() {

parent::__construct();

echo " Konstrukcja klasy pochodnej \n";

}

W konstruktorze klasy Pochodna wywołujemy konstruktora rodzica. Używamy słowa

parent, a następnie dwa dwukropki i metodę __construct(). Konstruktor klasy

bazowej musi być jawnie wywołany.

Uazz.pl Strona 25

$obj1 = new Podstawowa();

$obj2 = new Pochodna();

Możemy utworzyć bazy podstawowe i klasy pochodne.

$ php klasy.php

Konstrukcja klasy podstawowej

Konstrukcja klasy podstawowej

Konstrukcja klasy pochodnej

To dane wyjściowe skryptu PHP.

Przykład bardziej skomplikowanego skryptu.

<?php

abstract class Istota {

protected $jestZywy = true;

public function jestZywy() {

if ($this->jestZywy) {

echo "Istota jest żywa\n";

} else {

echo "Istota jest nie żywa\n";

}

}

public function kill() {

$this->jestZywy = false;

}

}

abstract class Zwierze extends Istota {

protected $wiek;

public function __construct($wiek) {

$this->wiek = $wiek;

}

protected function setAge($wiek) {

$this->wiek = $wiek;

}

public function getAge() {

return $this->wiek;

}

Uazz.pl Strona 26

}

class Kot extends Zwierze {

private $imie;

public function __construct($imie, $wiek) {

$this->ime = $imie;

parent::__construct($wiek);

}

public function getName() {

return $this->imie;

}

}

$kot = new Kot("Tofik", 4);

$kot->jestZywy();

echo $kot->getName() . " ma " . $kot->getAge() . " lat(a)\n";

$kot->kill();

$kot->jestZywy();

?>

Użyliśmy tutaj kilka nowych koncepcji. W przykładowym kodzie mamy trzy klasy.

Istota, Zwierze i Kot. Klasa Zwierze dziedziczy z klasy Istota. Klasa Kot dziedziczy z

klasy Zwierze. Klasy dziedziczą metody i elementy danych, które nie zostały

zadeklarowane, jako prywatne.

abstract class Istota {

Klasa Istota jest zadeklarowana za pomocą słowa abstract. Słowo kluczowe

abstract zakazuje wystąpienia klasy. Nie ma sensu aby utworzyć wystąpienie klasy

Istota.

protected $jestZywy = true;

Właściwość (zmienna, pole) $jestZywy jest zadeklarowana za pomocą słowa

protected. Właściwości są dostępne tylko dla klas, w których zostały zadeklarowane

oraz w klasach potomnych.

abstract class Zwierze extends Istota {

Klasa Animal jest również uznana za abstrakcyjną. Dziedziczy z klasy Istota. W tym

celu możemy użyć słowa kluczowego extends. Klasa Zwierze jest potomkiem.

Dziedziczy metody i zmienne klasy bazowej Istota.

class Kot extends Zwierze {

Uazz.pl Strona 27

Klasa Kot dziedziczy z klasy Zwierze. Dziedziczy z klasy Zwierze i pośrednio z klasy Istota.

Ta klasa nie jest zadeklarowana, jako abstrakcyjna, co oznacza, możemy używać jej

instancję.

parent::__construct($wiek);

W konstruktorze klasy Kot, wywołujemy konstruktor rodzica przy użyciu słowa

parent, następnie przez dwa dwukropki i metodę __ construct (). Konstruktor

klasy dominującej musi być wywołany jawnie.

$kot = new Kot("Tofik", 4);

$kot->jestZywy();

echo $kot->getName() . " ma " . $kot->getAge() . " lat(a)\n";

$kot->kill();

$kot->jestZywy();

Tworzymy nowy obiekt Kot. Tofik, 4 lat. Następnie wywołujemy funkcje na obiekcie

Tofik. Należy zwrócić uwagę na wykorzystanie metod, które nie zostały utworzone w

klasie Kot, ale dziedziczone z klas nadrzędnych.

$ php dziedziczenie.php

Istota jest żywa

ma 4 lat(a)

Istota jest nie żywa

Dane wyjściowe skryptu.

Uazz.pl Strona 28

Klasy abstrakcyjne i metody

PHP 5 wprowadza klasy i metody abstrakcyjne. Nie można utworzyć wystąpienia

klasy abstrakcyjnej. Jeśli Klasa zawiera, co najmniej jedną metoda abstrakcyjna, musi

być zadeklarowana także, jako abstrakcyjna. Metody abstrakcyjne nie mogą być

implementowane. Kiedy możemy dziedziczyć z klasy abstrakcyjnej, wszystkie metody

abstrakcyjne muszą być zaimplementowane w klasie pochodnej. Ponadto metody te

muszą być zadeklarowane z tą samą ograniczoną widocznością.

Unlike interfaces, abstract classes may have methods with full implementation and

may also have defined member fields. So abstract classes may provide a partial

implementation. Programmers often put some common functionality into abstract

classes. And these abstract classes are later subclassed to provide more specific

implementation. For example, the Qt graphics library has a QAbstractButton, which

is the abstract base class of button widgets, providing functionality common to

buttons. Buttons Q3Button, QCheckBox, QPushButton, QRadioButton, and

QToolButton inherit from this base abstract class.

W przeciwieństwie do interfejsów (interfaces) klasy abstrakcyjne mogą mieć

metody z pełną implementacją i mogą również mieć zdefiniowane właściwości

(zmienne). Więc klasy abstrakcyjne mogą zapewnić częściową implementacje.

Programiści często umieszczają niektóre typowe funkcje w klasach abstrakcyjnych.

Klasy abstrakcyjne zapewniają podklasom określone implementacje. Na przykład

biblioteka graficzna Qt ma QAbstractButton, która jest abstrakcyjną klasą z

podstawowymi wzorami przycisków, zapewniając funkcje wspólne dla przycisków.

Przyciski Q3Button, QCheckBox, QPushButton, QRadioButton i QToolButton

dziedziczą z tej podstawowej klasy abstrakcyjnej.

Formalnie mówiąc, abstrakcyjne klasy są używane do wymuszania protokołu.

Protokół to zestaw czynności, które muszą obsługiwać wszystkie obiekty wykonawcze.

<?php

abstract class Rysunek {

protected $x = 0;

protected $y = 0;

public abstract function obszar();

public function getCoordinates() {

Uazz.pl Strona 29

echo "\$x is $this->x\n";

echo "\$y is $this->y\n";

}

}

class Kolo extends Rysunek {

private $promien;

public function __construct($x, $y, $r) {

$this->promien = $r;

$this->x = $x;

$this->y = $y;

}

public function obszar() {

return $this->promien * $this->promien * pi();

}

public function __toString() {

return " Koło, w x: $this->x, y: $this->y, promień: $this->promien";

}

}

$o = new Kolo(12, 45, 22);

echo "$o \n";

echo " Obszar koła: " . $o->obszar() . "\n";

echo $o->getCoordinates();

?>

W naszym skryptcie PHP mamy abstrakcyjną klasę podstawową Rysunek. Klasa

definiuje dwa pola (właściwości, zmienne), definiuje jedną metodę i deklaruje, jedną

metodę. Jedna z metod jest abstrakcyjna, druga jest w pełni implementowana. Klasa

Rysunek jest abstrakcyjna, ponieważ nie możemy rysować. Mamy narysować okrąg,

kropkę lub kwadrat. Klasa Rysunek ma pewne typowe funkcje dla obiektów, które

można wyciągnąć.

class Kolo extends Rysunek {

Klasa Kolo jest podklasą klasy Rysunek. Ona musi implementować abstrakcyjne

metody.

$ php abstrakt.php

Koło, w x: 12, y: 45, promień: 22

Obszar koła: 1520.5308443375

$x is 12

$y is 45

Uazz.pl Strona 30

Dane wyjściowe skryptu.

Uazz.pl Strona 31

Interfejsy

Pilot zdalnego sterowania jest interfejsem pomiędzy widzem i telewizorem. Jest to

interfejs do elektronicznych urządzeń. Protokół dyplomatyczny prowadzi wszystkie

działania w dyplomacji. Przepisy ruchu drogowego są to reguły, które muszą

przestrzegać kierowcy, rowerzyści i piesi. Interfejsy programowania są analogiczne w

poprzednich przykładach.

Interfaces are:

Interfejsy są:

APIs

Contracts

Obiekty wchodzą w interakcje ze światem zewnętrznym za pomocą metod. Faktyczna

implementacja nie jest ważna dla programisty, lub też może być to dla niego tajne.

Firma może sprzedawać biblioteki i nie chce ujawniać rzeczywistych realizacji.

Programista może wywołać metodę maximize() okna narzędzi GUI, ale nie wie nic na

temat jak ta metoda jest implementowana. Z tego punktu widzenia interfejsy są to

metody, za pomocą, których obiekty wchodzą w interakcję ze światem zewnętrznym,

nie narażając zbytnio ich wewnętrzne funkcjonowanie.

Z drugiego punktu widzenia interfejsy są jedynie zbiorem ściśle określonych reguł..

Jeżeli są one uzgodnione, muszą one być stosowane. Są one używane do

projektowania architektury aplikacji. One pomagają w zorganizowaniu kodu.

Interfejsy są to całkowicie abstrakcyjne typy. One są deklarowane przy użyciu słowa

kluczowego interface. Interfejsy może mieć tylko zadeklarowane metody. Wszystkie

metody zadeklarowane w interfejsie muszą być publiczne. One nie moją pełnej

implementacji metody, ani pola (zmienne). Klasy PHP mogą implementować

dowolną liczbę interfejsów. Interfejs można rozszerzać dowolną liczbą interfejsów.

Klasa, która implementuje interfejs musi implementować wszystkie metody

interfejsu.

Interfejsy są używane do symulowania wielokrotnego dziedziczenia. Klasy PHP

można rozszerzyć tylko jedną klasą. Klasy PHP mogą zaimplementować wiele

interfejsów. W wielokrotnym dziedziczeniu przy użyciu interfejsów nie chodzi o

Uazz.pl Strona 32

dziedziczenie metod i zmiennych. Chodzi o dziedziczenie pomysłów lub umów, które

są opisane przez interfejsy.

Istnieje jedna istotna różnica między interfejsem i klasą abstrakcyjną. Klasy

abstrakcyjne dostarczają częściową implementację dla klas, które są związane w

hierarchii dziedziczenia. Interfejsy z drugiej strony mogą być implementowane przez

klasy, które nie są powiązane ze sobą. Na przykład mamy dwa przyciski. Klasyczny

przycisk i okrągły przycisk. Oba dziedziczą z klasy abstrakcyjnej przycisk, która

zapewnia pewne typowe funkcje dla wszystkich przycisków. Innym przykładem mogą

być klasy Database i SignIn. Nie są one powiązane ze sobą. Możemy zastosować

interfejs ILoggable, który miał zmusić ich do utworzenia metody do logowania.

<?php

interface IInfo {

public function do_inform();

}

class Some implements IInfo {

public function do_inform() {

echo "To jest przykładowa klasa\n";

}

}

$sm = new Some();

$sm->do_inform();

?>

Jest to prosty skrypt PHP, demonstrujący interfejs.

interface IInfo {

public function do_inform();

}

Jest to interfejs IInfo. Deklaracja metody do_inform().

class Some implements IInfo {

Używamy słowa implements do implementacji interfejsu.

public function do_inform() {

echo " To jest przykładowa klasa \n";

}

Uazz.pl Strona 33

Klasa dostarcza implementację metody do_inform().

W następnym przykładzie pokazano, jak klasa może zaimplementować wiele

interfejsów.

<?php

interface Device {

public function switch_on();

public function switch_off();

}

interface Volume {

public function volume_up();

public function volume_down();

}

interface Pluggable {

public function plug_in();

public function plug_off();

}

class CellPhone implements Device, Volume, Pluggable {

public function switch_on() { echo " Włączanie \n"; }

public function switch_off() { echo " Wyłączanie \n"; }

public function volume_up() { echo "Głośniej\n"; }

public function volume_down() { echo "Ciszej\n"; }

public function plug_in() { echo "Podłączanie\n"; }

public function plug_off() { echo "Odłączanie\n"; }

}

$o = new CellPhone();

$o->switch_on();

$o->volume_up();

$o->plug_in();

?>

Mamy klasę CellPhone, która dziedziczy z trzech interfejsów.

class CellPhone implements Device, Volume, Pluggable {

Klasy implementuje wszystkie trzy interfejsy, które są przedzielone przecinkiem.

Klasa CellPhone musi implementować wszystkie metody ze wszystkich trzech

interfejsów.

$ php interfejs.php

Włączanie

Uazz.pl Strona 34

Głośniej

Podłączanie

Uruchamianie skryptu PHP.

W następnym przykładzie pokazano, jak rozszerzyć interfejsy przez wiele innych

interfejsów.

<?php

interface IInfo {

public function do_inform();

}

interface IVersion {

public function get_version();

}

interface ILog extends IInfo, IVersion {

public function do_log();

}

class DBConnect implements ILog {

public function do_inform() {

echo "To jest klasa DBConnect\n";

}

public function get_version() {

echo "Wersja 1.02\n";

}

public function do_log() {

echo "Logowanie\n";

}

public function connect() {

echo "Łączenie z bazą danych\n";

}

}

$db = new DBConnect();

$db->do_inform();

$db->get_version();

$db->do_log();

$db->connect();

?>

W tym skrypcie PHP możemy zdefiniować trzy interfejsy. Rozszerzenie interfejsów

pozwala nam zorganizować je.

Uazz.pl Strona 35

interface ILog extends IInfo, IVersion {

public function do_log();

}

Interfejs ILog rozszerza inne dwa interfejsy.

public function do_inform() {

echo " To jest klasa DBConnect \n";

}

Klasa DBConnect implementuje metodę do_inform(). Metoda ta została

odziedziczona przez interfejs ILog, który implementuje klasę.

Uazz.pl Strona 36

Polimorfizm

Polimorfizm jest to proces, który używa operator lub funkcję w różny sposób dla

różnych danych wejściowych. W praktyce polimorfizm oznacza, że jeśli Klasa B

dziedziczy z klasy A, nie musi dziedziczyć wszystkiego z klasy A; może zrobić kilka

rzeczy z tej klasy.

Ogólnie rzecz biorąc polimorfizm jest to zdolność do tworzenia kilku obiektów z

określonych klas bazowych. Technicznie rzecz biorąc jest to zdolność

przedefiniowania metod klasy pochodnej. Polimorfizm dotyczy stosowania określonej

implementacji interfejsu lub bardziej ogólnie klasy podstawowej.

<?php

abstract class Ksztalt {

private $x = 0;

private $y = 0;

public abstract function area();

}

class Prostokat extends Ksztalt {

function __construct($x, $y) {

$this->x = $x;

$this->y = $y;

}

function area() {

return $this->x * $this->y;

}

}

class Kwadrat extends Ksztalt {

function __construct($x) {

$this->x = $x;

}

function area() {

return $this->x * $this->x;

}

}

$shapes = array(

new Kwadrat(5),

new Prostokat(12, 4),

new Kwadrat(8)

);

foreach ($shapes as $shape) {

echo $shape->area() . "\n";

Uazz.pl Strona 37

}

?>

W powyższym skrypcie PHP mamy klasę abstrakcyjną Kształt. Ta klasa przemienia

się w dwie klasy podrzędne, Prostokat i Kwadrat. Oba rozwiązania zapewniają

realizację metody area(). Polimorfizm przynosi elastyczności i skalowalność

systemów OOP.

Uazz.pl Strona 38

Programowanie obiektowe II

W tym rozdziale kursu PHP nadal opisujemy OOP w języku PHP.

Słowa kluczowe static

Możemy zadeklarować właściwości klasy i metody jako static (statyczne). Statyczne

właściwości i metody nie należą do instancji klasy. Należą one do samej klasy. Są one

dostępne przez operator (::).

<?php

class Sys {

public static function println($string) {

echo "$string\n";

}

}

Sys::println("PHP");

Sys::println("PERL");

Sys::println("Python");

Sys::println("Pike");

?>

W powyższym skrypcie PHP mamy metodę statyczną (static) println(). Wyświetla

ciąg i przechodzi do nowej linii. W tym przykładzie wywodzi się z języka Java.

Sys::println("PHP");

Nie potrzebujemy w obiekcie wywoływać metody println(). Wywołujemy metody

statyczne (static) określając nazwę klasy, a następnie używamy operatora podwójny

dwukropek i jej nazwę.

$ php static1.php

PHP

PERL

Python

Pike

Powyżej dane wyjściowe skryptu.

Uazz.pl Strona 39

<?php

class Math {

public static $PI = 3.14159265359;

}

echo Math::$PI . "\n";

?>

I teraz mamy przykład ze zmienną statyczną.

echo Math::$PI . "\n";

Możemy uzyskać dostęp do zmiennej określając nazwę klasy, i następnie operator

zakresu i nazwę zmiennej.

Uazz.pl Strona 40

Słowo kluczowe final

Jeżeli metoda zostanie zdefiniowana z użyciem słowa kluczowego final, to nie będzie

mogła zostać nadpisana w żadnej podklasie. Użycie słowa kluczowego final jest

kwestią projektowania aplikacji. Niektóre klasy nie powinny być rozszerzane i

niektóre metody nie powinny być nadpisane. To zachowanie jest egzekwowane przez

słowo final.

<?php

class Podstawowa {

final function say() {

echo " Klasa podstawowa ";

}

}

class Pochodna extends Podstawowa {

function say() {

echo " Klasa pochodna ";

}

}

?>

Ten skrypt PHP nie uruchomi się. Możemy dostać błąd " Cannot override final

method Base::say()".

<?php

final class Math {

static function getPI() {

return 3.141592;

}

}

class DerivedMath extends Math {

function say() {

echo "DerivedMath class";

}

}

?>

Uazz.pl Strona 41

W poprzednim skrypcie PHP mamy prototyp klasy podstawowej Math. Jedynym

celem tej klasy jest zapewnienie kilka pomocnych metod i stałych. (W naszym

przypadku mamy tylko jedną metodę). Nie jest tworzona jako rozszerzona. Aby

uniknąć nadpisywania metod przez innych programistów, aby nie mogli dziedziczyć z

tej klasy, twórcy przygotowali klasę, jako final. Jeśli ty spróbujesz uruchomić ten

skrypt PHP, otrzymasz następujący komunikat o błędzie: "Fatal error: Class

DerivedMath may not inherit from final class (Math)". ("błąd krytyczny: Klasa

DerivedMath nie może dziedziczyć z klasy final (Math)".)

Uazz.pl Strona 42

Deep copy vs shallow copy

Kopiowanie danych jest ważnym zadaniem w programowaniu. Obiekt jest to złożony

typ danych w OOP. Pola w obiekcie mogą być przechowywane przez wartość lub przez

odwołanie. Kopiowanie można wykonać na dwa sposoby.

Płytkie kopiowanie (shallow copy ) kopiuje wszystkie wartości i odwołania do

nowego wystąpienia. Dane do którego wskazuje odwołanie nie są kopiowane; tylko

wskaźnik jest kopiowany. Nowe odniesienia są skierowane do oryginalnych obiektów.

Żadne zmiany pól odniesienia nie wpływają na oba obiekty.

Głębokie kopie (deep copy) kopiują wszystkie wartości do nowego wystąpienia. W

przypadku pól, które są przechowywane, jako głębokie kopie wykonuje głębokie kopii

danych, do którego istnieje odwołanie. Nowa kopia obiektu tworzona jest przez

odwołanie. A wskaźnik do nowo utworzonego obiektu. Zmiany w tym obiekcie nie

wpłyną na inne kopie obiektu. Głębokie kopie w pełni replikują obiekty.

In PHP, we have a copy keyword, which performs a shallow copy by default. It calls

the object's __clone() method. We can implement the method to create our custom

deep copy. In PHP 5, all objects are assigned by reference.

W PHP mamy słowo kluczowe copy, które wykonuje płytkie kopię domyślnie. To

wywołuje metodę obiektu __clone(). Używamy tę metodę, aby utworzyć

egzemplarz, przez głębokie kopiowanie. W PHP 5 wszystkie obiekty są przypisane

przez referencję.

Następne dwa przykłady wykonają płytkie i głębokie kopie obiektów.

<?php

class Objekt {

public $id;

public $rozmiar;

public $kolor;

function __construct($id, $rozmiar, $kolor) {

$this->id = $id;

$this->rozmiar = $rozmiar;

$this->kolor = $kolor;

}

}

Uazz.pl Strona 43

class Kolor {

public $czerwony;

public $zielony;

public $niebieski;

function __construct($czerwony, $zielony, $niebieski) {

$this->czerwony = $czerwony;

$this->zielony = $zielony;

$this->niebieski = $niebieski;

}

}

$kolor = new Kolor(23, 42, 223);

$object1 = new Objekt(23, "maly", $kolor);

$object2 = clone $object1;

$object2->id++;

$object2->kolor->czerwony = 255;

$object2->rozmiar = "duzy";

print_r($object1);

print_r($object2);

?>

W powyższym skrypcie PHP definiujemy dwa obiekty niestandardowe. Obiekt i Kolor.

Obiekt będzie miał odwołanie do obiektu Kolor.

$kolor = new Kolor(23, 42, 223);

Tworzymy nową instancję obiektu Kolor.

$object1 = new Objekt(23, "maly", $kolor);

Tworzona jest instancja klasy Objekt. Wystąpienie obiektu Kolor przechodzi do jego

konstruktora.

$object2 = clone $object1;

Wykonujemy płytkie kopie obiektu.

$object2->id++;

$object2->kolor->czerwony = 255;

$object2->rozmiar = "duzy";

Tutaj możemy modyfikować pola sklonowanego obiektu. Zwiększamy identyfikator,

zmieniamy częściowo czerwony kolor obiektu i zmieniamy rozmiar na "duzy".

print_r($object1);

print_r($object2);

Uazz.pl Strona 44

Używamy funkcji print_r() aby porównać wyniki.

$ php plytkakopia.php

Objekt Object

(

[id] => 23

[rozmiar] => maly

[kolor] => Kolor Object

(

[czerwony] => 255

[zielony] => 42

[niebieski] => 223

)

)

Objekt Object

(

[id] => 24

[rozmiar] => duzy

[kolor] => Kolor Object

(

[czerwony] => 255

[zielony] => 42

[niebieski] => 223

)

)

Widzimy, że identyfikatory są różne. 23 vs 24. Rozmiar jest inny. "mały" vs "duzy".

Ale kolor czerwony dla obiektu jest taki sam dla obu wystąpień. 255. Zmiana wartości

pola obiektu sklonowanego nie miał wpływu na oryginalny obiekt. Zmiana pola

odwołania wpłynęło także na oryginalny obiekt. Innymi słowy oba obiekty odnoszą się

do tego samego koloru obiektu w pamięci.

Aby zmienić to zachowanie, zrobimy głęboką kopię poniżej.

Uazz.pl Strona 45

<?php

class Objekt {

public $id;

public $rozmiar;

public $kolor;

function __construct($id, $rozmiar, $kolor) {

$this->id = $id;

$this->rozmiar = $rozmiar;

$this->kolor = $kolor;

}

function __clone() {

$czerwony = $this->kolor->czerwony;

$zielony = $this->kolor->zielony;

$niebieski = $this->kolor->niebieski;

$this->kolor = new Kolor($czerwony, $zielony, $niebieski);

}

}

class Kolor {

public $czerwony;

public $zielony;

public $niebieski;

function __construct($czerwony, $zielony, $niebieski) {

$this->czerwony = $czerwony;

$this->zielony = $zielony;

$this->niebieski = $niebieski;

}

}

$kolor = new Kolor(23, 42, 223);

$object1 = new Objekt(23, "maly", $kolor);

$object2 = clone $object1;

$object2->id++;

$object2->kolor->czerwony = 255;

$object2->rozmiar = "duzy";

print_r($object1);

print_r($object2);

?>

W tym skrypcie PHP zaimpletowaliśmy metodę __clone().

function __clone() {

$red = $this->kolor->czerwony;

$green = $this->kolor->zielony;

$blue = $this->kolor->niebieski;

Uazz.pl Strona 46

$this->kolor = new Kolor($czerwony, $zielony, $niebieski);

}

Wewnątrz metody __clone() kopiujemy pola czerwony, zielony i niebieski i

tworzymy nowy obiekt Kolor. Teraz pole $kolor wskazuje na inny kolor obiektu.

$ php glebokakopia.php

Objekt Object

(

[id] => 23

[rozmiar] => maly

[kolor] => Kolor Object

(

[czerwony] => 23

[zielony] => 42

[niebieski] => 223

)

)

Objekt Object

(

[id] => 24

[rozmiar] => duzy

[kolor] => Kolor Object

(

[czerwony] => 255

[zielony] => 42

[niebieski] => 223

)

)

Teraz kolor czerwony obiektu Kolor nie jest taki sam. Oryginalny obiekt zachował

swoją poprzednią wartość 23.

Uazz.pl Strona 47

Wyjątki

Wyjątki są zaprojektowane do obsługi występowania wyjątków, są to specjalne

warunki, które zmieniają tok normalnego wykonywania programu. Wyjątki są

wywoływane, wyrzucane lub inicjowane.

Podczas realizacji naszej aplikacji wiele rzeczy może pójść źle. Dysk może zostać

zapełniony i nie możemy zapisać naszego pliku. Połączenie z Internetem może zostać

przerwane i nasza aplikacja próbuje połączyć się z witryną. Wszystko to może

doprowadzić do awarii naszej aplikacji. Aby zapobiec, takim przypadkom, my musimy

radzić sobie z wszystkimi możliwymi błędami, które mogą wystąpić. Do tego możemy

użyć obsługi wyjątków.

Wyjątki zostały dopiero niedawno wprowadzone do języka PHP 5. Większość błędów

PHP nadal używa starego raportowanie błędów a nie wyjątki. Funkcja

set_error_handler() możemy użyć do obsługi błędów w skrypcie.

<?php

set_error_handler("error_handler");

function error_handler($errno, $errstring, $errfile, $line, $trace) {

throw new ErrorException($errstring, $errno, 0, $errfile, $line);

}

try {

$a = 0;

$b = 32;

$c = $b / $a;

} catch(ErrorException $e) {

echo " Wystąpił błąd \n";

echo $e->getMessage(), "\n";

}

?>

W powyższym skrypcie PHP celowo podzieliliśmy liczbę przez zero. Prowadzi to do

błędu. Ten błąd nie jest wyjątkiem i nie zostaje wychwycony przez słowo kluczowe

catch.

set_error_handler("error_handler");

Funkcja set_error_handler() ustawia funkcję obsługi błędów zdefiniowanych

przez użytkownika.

Uazz.pl Strona 48

function error_handler($errno, $errstring, $errfile, $line, $trace) {

throw new ErrorException($errstring, $errno, 0, $errfile, $line);

}

Wewnątrz funkcji set_error_handler() wrzucamy ErrorException. Wyjątek ten

później zostanie przechwycony przez słowo kluczowe catch.

try {

$a = 0;

$b = 32;

$c = $b / $a;

}

Kod, który sprawdzamy przed błędem jest umieszczany wewnątrz bloku po słowie

kluczowym try.

} catch(Exception $e) {

echo $e->getMessage();

}

Słowo kluczowe catch jest używane do przechwycenia wyjątku, który miał miejsce.

Aby dowiedzieć się więcej, możemy wywołać metodę getMessage() na obiekcie

wyjątku.

$ php zerodzielenie.php

Wystąpił błąd

Division by zero

Powyżej wynik działania naszego skryptu.

Exception jest klasą bazową dla wszystkich wyjątków. Możemy stworzyć własne

wyjątki z tej klasy podstawowej.

<?php

define("LIMIT", 333);

class BigValueException extends Exception {

public function __construct($message) {

parent::__construct($message);

}

}

$a = 34325;

try {

if ($a > LIMIT) {

Uazz.pl Strona 49

throw new BigValueException("Przekroczono maksymalną wartość

dozwoloną \n");

}

} catch (BigValueException $e) {

echo $e->getMessage();

}

?>

Powiedzmy, że mamy sytuację, w której nie możemy poradzić sobie z dużymi cyframi.

define("LIMIT", 333);

Liczby większe od tej stałej uznawane są za "duże" przez nasz skrypt PHP.

class BigValueException extends Exception {

We have a BigValueException class. This class derives from the Exception class

through the extends keyword.

Mamy klasę BigValueException. Klasa ta wywodzi się z klasy Exception poprzez

słowo kluczowe extends.

public function __construct($message) {

parent::__construct($message);

}

Wewnątrz konstruktora możemy wywołać Konstruktor rodzica.

if ($a > LIMIT) {

throw new BigValueException("Przekroczono maksymalną wartość dozwoloną

\n");

}

Jeśli wartość jest większa niż limit, rzucamy nasze niestandardowe wyjątek.

Podajemy wyjątek komunikat "Przekroczono maksymalną wartość dozwoloną".

} catch (BigValueException $e) {

echo $e->getMessage();

}

Przechwytujemy wyjątek i wyświetlamy go na konsoli.

Uazz.pl Strona 50

Konstruktor przeciążenia

Konstruktor przeciążenia nie jest obsługiwany w języku PHP. Innymi słowy każda

klasa może mieć tylko jeden Konstruktor zdefiniowany. Wielu programistów, zna,

rozwiązania z języków Java czy C# i szuka podobnych funkcji w PHP. Istnieją dwa

sposoby, aby sobie z tym poradzić.

Pierwsze rozwiązanie jest oparte na funkcji func_get_args(). Drugie rozwiązanie

wykorzystuje factory pattern (wzorzec Fabryka).

<?php

class Ksiazka {

private $tytul = " nie określono ";

private $autor = " nie określono ";

private $rok = " nie określono ";

public function __construct() {

$args = func_get_args();

foreach(array("tytul", "autor", "rok") as $item)

{

if(empty($args)) {

break;

}

$this->$item = array_shift($args);

}

}

public function __toString() {

return "Autor: $this->autor\nTytuł: $this->tytul\nWydano: $this-

>rok\n\n";

}

}

$ksiazka1 = new Ksiazka("Barry Burd", "Java for Dummies");

echo $ksiazka1;

$ksiazka2 = new Ksiazka("Paul Wilton", "JavaScript", 2010);

echo $ksiazka2;

?>

W skrypcie powyżej mamy klasę Ksiazka. Możemy utworzyć wystąpienia klasy 2 i 3

parametrami.

private $tytul = " nie określono ";

private $autor = " nie określono ";

Uazz.pl Strona 51

private $rok = " nie określono ";

Mamy zdefiniowane trzy pola. Ich wartość początkowa jest "nie określona".

$args = func_get_args();

Funkcja func_get_args() zwraca tablicę zawierający listę argumentów funkcji. Więc

chodzi o to: kod wewnątrz konstruktora jest dynamiczny, to zależy od argumentów

przekazywanych do niego.

foreach(array("tytul", "autor", "rok") as $item)

Przechodzimy przez wszystkie pola(zmienne) za pomocą słowa kluczowego foreach.

$this->$item = array_shift($args);

Jednym z najbardziej podstawowych zadań konstruktorów jest zainicjować pola

klasy. Odbywa się to w powyższej linii kodu. Funkcja array_shift ()usuwa pierwszy

element z tablicy i zwraca go.

$ksiazka1 = new Ksiazka("Barry Burd", "Java for Dummies");

$ksiazka2 = new Ksiazka("Paul Wilton", "JavaScript", 2010);

Mamy dwa różne konstruktory. Pierwszy ma 2 parametry, drugi 3.

$ php konstruktor.php

Autor: Java for Dummies

Tytuł: Barry Burd

Wydano: nie określono

Autor: JavaScript

Tytuł: Paul Wilton

Wydano: 2010

Jest to wynik działania skryptu.

Uazz.pl Strona 52

W następnym przykładzie kodu Konstruktor przeciążenia symuluje przy użyciu

wzorca Fabryki. Fabryka abstrakcyjna (ang. Abstract Factory) jest to jeden z

kreacyjnych wzorców projektowych (obiektowy), którego celem jest dostarczenie

interfejsu do tworzenia różnych obiektów jednego typu (tej samej rodziny) bez

specyfikowania ich konkretnych klas. Umożliwia jednemu obiektowi tworzenie

różnych, powiązanych ze sobą, reprezentacji podobiektów określając ich typy podczas

działania programu. (Wikipedia)

<?php

class Kot {

private $imie = "unspecified";

private $wiek = "unspecified";

public static function withName($imie) {

$kot = new Kot();

$kot->imie = $imie;

return $kot;

}

public static function withAge($wiek) {

$kot = new Kot();

$kot->wiek = $wiek;

return $kot;

}

public static function fullCat($imie, $wiek) {

$kot = new Kot();

$kot->imie = $imie;

$kot->wiek = $wiek;

return $kot;

}

public function __toString() {

return "Imie: $this->imie, Wiek: $this->wiek\n";

}

}

$cici = Kot::withName("Miau");

echo $cici;

$missy = Kot::withAge(8);

echo $missy;

$tofik = Kot::fullCat("Tofik", 5);

echo $tofik;

?>

Uazz.pl Strona 53

W powyższym skrypcie PHP mamy klasę Kot typu wzorzec fabryka. Posiada trzy

różne funkcje statyczne. Każda z nich zwraca obiekt kot.

private $name = "unspecified";

private $age = "unspecified";

Mamy dwa pola. Ich wartość początkowa jest "nieokreślona" (unspecified).

public static function withName($imie) {

$kot = new Kot();

$kot->imie = $imie;

return $kot;

}

Tutaj jest funkcja withName(). Ta funkcja tworzy instancję klasy Kot. Ustawia pole

i zwraca obiekt.

$cici = Kot::withName("Cici");

echo $cici;

Tworzymy wystąpienie cat z jednej z metod fabryki. Funkcja echo obiektu. np.

wywołanie metody __toString() klasy.

$ php factory.php

Name: Cici, Age: unspecified

Name: unspecified, Age: 6

Name: Lucky, Age: 4

Dane wyjściowe skryptu.

W tej części kursu PHP kontynuowaliśmy dyskusję na temat programowania

obiektowego w PHP.