PL PHP programowanie obiektowe

background image



PHP programowanie obiektowe

Wprowadzenie do OOP w PHP


2013-01-21

Uazz.pl

background image

Uazz.pl

Strona 2

background image

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

background image

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.

background image

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

(

background image

Uazz.pl

Strona 6

)

object

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

object

.

background image

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

background image

Uazz.pl

Strona 8

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

background image

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.

background image

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.

background image

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.

background image

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.

background image

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.

background image

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().

background image

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ść.

background image

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 zawsz

e __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";
}
}

background image

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;

background image

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

background image

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.

background image

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);

background image

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.

background image

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);

background image

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.

background image

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.

background image

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;
}

background image

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 {

background image

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.

background image

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() {

background image

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

background image

Uazz.pl

Strona 30

Dane wyjściowe skryptu.

background image

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

background image

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";
}

background image

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

background image

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.

background image

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ę.

background image

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";

background image

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.

background image

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.

background image

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.

background image

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";
}
}

?>

background image

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)".)

background image

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;
}
}

background image

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);

background image

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.

background image

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;

background image

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.

background image

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.

background image

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) {

background image

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.

background image

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 ";

background image

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.

background image

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;

?>

background image

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.


Wyszukiwarka

Podobne podstrony:
PHP Programowanie obiektowe phppro
PHP Programowanie obiektowe
PHP Programowanie obiektowe phppro
PHP Programowanie obiektowe
PHP Programowanie obiektowe phppro
PHP Programowanie obiektowe phppro
PHP Programowanie obiektowe 2
Ebook Peter Lavin Php Programowanie Obiektowe (Phppro) Helion Onepress Free Ebook Darmowy Ebook
PHP Programowanie obiektowe phppro
obiektowka PHP, Programowanie
PHP profesjonalnie programowanie obiektowe i narzędzia programisty 08 2006
Programowanie obiektowe w PHP 5
obiektowka PHP 2, Programowanie

więcej podobnych podstron