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.