PHP programowanie obiektowe
Wprowadzenie do OOP w PHP
2013-01-21
Uazz.pl
Uazz.pl
Strona 2
Uazz.pl
Strona 3
Zawartość
PHP programowanie obiektowe ............................................................................. 1
PHP programowanie obiektowe ............................................................................. 4
Obiekty ............................................................................................................................... 5
Atrybuty obiektu .......................................................................................................... 7
Metody................................................................................................................................ 9
Modyfikatory dostępu ............................................................................................. 11
Metoda przeciążania ................................................................................................ 14
Konstruktor ................................................................................................................... 16
Stałe w klasie ............................................................................................................... 19
Słowo kluczowe instanceof ................................................................................. 20
Metoda __toString() ................................................................................................ 22
Dziedziczenie ............................................................................................................... 24
Klasy abstrakcyjne i metody .............................................................................. 28
Interfejsy ....................................................................................................................... 31
Polimorfizm ................................................................................................................... 36
Słowa kluczowe static ............................................................................................ 38
Słowo kluczowe final ............................................................................................... 40
Deep copy vs shallow copy .................................................................................. 42
Wyjątki ............................................................................................................................. 47
Konstruktor przeciążenia ..................................................................................... 50
Uazz.pl
Strona 4
PHP programowanie obiektowe
W tej części kursu PHP będziemy mówić o obiektowym programowaniu w PHP.
Istnieją trzy powszechnie stosowane paradygmaty programowania. Programowanie
proceduralne, programowanie funkcjonalne i programowanie obiektowe. PHP 5
obsługuje zarówno proceduralne, jak i obiektowe programowanie. We wcześniejszych
wersjach PHP miał ograniczone wsparcie lub był brak wsparcia dla OOP.
Programowanie obiektowe (OOP) jest paradygmatem programowania, który używa
obiektów i ich interakcje do projektowania aplikacji i programów komputerowych.
(Wikipedia)
Istnieją pewne podstawowe pojęcia programowania w OOP:
Abstraction (Abstrakcja)
Polymorphism (Polimorfizm)
Encapsulation (Hermetyzacja)
Inheritance (Dziedziczenie)
Abstrakcja jest to uproszczenie złożonej rzeczywistości przez modelowanie klas
odpowiednich do problemu. Polimorfizm jest to proces, który używa operatora lub
funkcji w różny sposób dla różnych danych wejściowych. Hermetyzacja ukrywa
szczegóły dotyczące implementacji klasy z innych obiektów. Dziedziczenie jest to
sposób, aby nowe klasy używały klas, które już zostały zdefiniowane.
Uazz.pl
Strona 5
Obiekty
Obiekty są podstawowym budulcem programu OOP w PHP. Obiekt jest to połączenie
danych i metod. W programie OOP możemy tworzyć obiekty. Obiekty te komunikują
się ze sobą za pomocą metod. Każdy obiekt może odbierać wiadomości, wysyłać
wiadomości i przetwarzać dane.
Istnieją dwa kroki w tworzeniu obiektu. Po pierwsze musimy utworzyć klasę. Klasa
jest szablonem dla obiektu. Jest to plan, który opisuje stan i zachowanie obiektów
klasy. Klasa może służyć do tworzenia wielu obiektów. Obiekty utworzone w czasie
wykonywania z klasy są nazywane instances (wystąpienia) danej klasy.
<?php
class Przyklad {}
$object = new Przyklad();
print_r($object);
echo gettype($object), "\n";
?>
W pierwszym przykładzie tworzymy prosty obiekt.
class Przyklad {}
To jest definicja prostej klasy. Zawartość szablonu jest pusta. Nie ma żadnych danych
ani metody.
$object = new Przyklad();
Tworzymy nową instancję klasy Przyklad. W tym celu uzywamy słowo kluczowe
new
.
Zmienna $object jest uchwytem do utworzonego obiektu.
print_r($object);
echo gettype($object), "\n";
Za pomocą funkcji
print_r()
uzyskujemy informacje na temat obiektu i funkcji
gettype()
, aby uzyskać typ zmiennej.
$ php klasa.php
Przyklad Object
(
Uazz.pl
Strona 6
)
object
Nie mamy tu wiele informacji, ponieważ definicja klasy była pusta. Typ zmiennej to
object
.
Uazz.pl
Strona 7
Atrybuty obiektu
Atrybuty obiektu to dane w instancji klasy. Atrybutami obiektu nazywane są zmienne
instancji lub pola. Zmienną instancji jest zmienna zdefiniowana w klasie, dla której
każdy obiekt w klasie ma osobną kopię.
<?php
class Osoba {
public $imie = "";
}
$p1 = new Osoba();
$p1->imie = "Janek";
$p2 = new Osoba();
$p2->imie = "Beata";
echo $p1->imie . "\n";
echo $p2->imie . "\n";
?>
W powyższym skrypcie PHP mamy klasę Osoba z jednym polem (zmienną).
$p1 = new Osoba();
$p1->imie = "Janek";
Tworzymy instancję klasy Osoba. I zestaw zmiennej $imie z wartością "Janek".
Używamy -> operatora, aby uzyskać dostęp do atrybutów obiektów.
$p2 = new Osoba();
$p2->imie = "Beata";
Tworzymy inne wystąpienie klasy Osoba. Tu możemy sobie ustawić zmienną "Beata".
echo $p1->imie . "\n";
echo $p2->imie . "\n";
Możemy wyświetlić zawartość zmiennych na konsoli.
$ php osoba.php
Janek
Beata
Uazz.pl
Strona 8
Widzimy, dane wyjściowe skryptu. Każde wystąpienie klasy Osoba ma osobną kopię
zmiennej $imie.
Uazz.pl
Strona 9
Metody
Metody są zdefiniowane w ciele klasy. Służą one do wykonywania operacji z
atrybutami naszych obiektów. Metody są istotne w koncepcji enkapsulacji
(hermetyzacji) paradygmatu OOP. Na przykład możemy mieć metodę connect() w
naszej klasie AccessDatabase. Nie musimy być informowani, jak dokładnie metoda
connect() łączy się z bazą danych. Wiemy tylko, że jest używana do łączenia się z bazą
danych. Jest to istotne w podziale obowiązków w programowaniu. Zwłaszcza w
dużych aplikacjach.
<?php
class Kolo {
public $promien;
function setRadius($promien) {
$this->promien = $promien;
}
function powierzchnia() {
return $this->promien * $this->promien * M_PI;
}
}
$c = new Kolo();
$c->setRadius(5);
echo $c->powierzchnia(), "\n";
?>
W przykładzie powyżej mamy klasę Kolo. Możemy zdefiniować dwie metody.
public $promien;
Mamy jedną zmienną (pole). Jest to promień okręgu. Słowo kluczowe
public
jest
specyfikatorem dostępu. Mówi, że zmienna jest w pełni dostępna z zewnątrz.
function setRadius($promien) {
$this->promien = $promien;
}
Jest to metoda setRadius(). Jest to normalna funkcja PHP. Tak nazywamy funkcje
zdefiniowane wewnątrz metody klasy. Zmienna
$this
jest to specjalna zmienna,
której używamy, aby odwołać się do zmiennej.
Uazz.pl
Strona 10
function area() {
return $this->promien * $this->promien * M_PI;
}
Metoda powierzchnia() zwraca powierzchnię koła.
M_PI
jest to stała wbudowana w
języku PHP.
$ php kolo.php
78.5398163397
Uruchomiony przykład.
Uazz.pl
Strona 11
Modyfikatory dostępu
Modyfikatory dostępu ustawiają widoczność pól i metod. PHP 5 ma trzy rodzaje
modyfikatorów dostępu.
Public
(publiczny),
private
( prywatne) i
protected
(chronione). Do public (publicznych) modyfikatorów można uzyskać dostęp z
dowolnego miejsca. Elementy protected mogą być dostępne tylko w obrębie samej
klasy i w klasach dziedziczonych i klasach rodziców. Elementy private (prywatne)
mogą być dostępne tylko w klasie, która definiuje element prywatny.
Modyfikatory dostępu służą do ochrony danych przed przypadkowymi zmianami.
Czyni to programy bardziej odporne na błędy.
<?php
class Osoba {
public $imie = "";
private $wiek;
}
$p = new Osoba();
$p->imie = "Janek";
#$p->wiek = 17;
echo $p->imie . "\n";
?>
W powyższy skrypcie PHP mamy dwie zmienne (pola). Jedna jest zadeklarowana jako
public (publiczna), a druga jako private (prywatna).
$p->imie = "Jane";
#$p->wiek = 17;
Mamy dostęp do zmiennej $imie z zewnątrz klasy. Przez zewnętrzny dostęp mamy na
myśli "nie w klasie". Wszystko jest OK, dopóki zmienna $imie jest zadeklarowana
jako publiczna (public). Dostęp do zmiennej $wiek nie jest możliwy. Prywatny
(private) modyfikator zabrania tego. Jeśli odkomentujemy linię kodu, będzie
wyświetlony komunikat 'Fatal error: Cannot access private property Person::$age'
error.
"błąd krytyczny: nie ma dostępu do właściwości prywatnej Osoba:: $wiek' błąd.
Uazz.pl
Strona 12
<?php
class Baza {
public $imie = "Baza";
protected $id = 6344;
private $is_defined = "tak";
}
class Rozszerzona extends Baza {
public function info() {
echo "To jest klasa Rozszerzona\n";
echo "Klasa dziedziczy: \n";
echo $this->imie . "\n";
echo $this->id . "\n";
echo $this->is_defined . "\n";
}
}
$informacja = new Rozszerzona();
$informacja->info();
?>
W tym skrypcie PHP mamy pochodne klasy, która rozszerza klasę bazową. Klasa
bazowa ma trzy pola. Wszystkie z innym modyfikatorem dostępu. Pole $is_defined
nie jest dziedziczone. Prywatny (private) modyfikator zapobiega temu.
public function info() {
Metoda info() ma publiczny (public) modyfikator dostępu. Oznacza to, może ona
zostać wywołana poza środowiskiem klasy.
$ php dostep.php
To jest klasa Rozszerzona
Klasa dziedziczy:
Baza
6344
$
Uruchomiając skrypt PHP, możemy otrzymać następujące wyniki. Pola publiczne i
chronione są dziedziczone, prywatne pole nie jest.
Uazz.pl
Strona 13
<?php
class SysInfo {
private function get_date() {
return date("Y/m/d");
}
private function get_version() {
return phpversion();
}
public function getInfo() {
$date = $this->get_date();
$wersja = $this->get_version();
echo "Data: $date\n";
echo "Wersja PHP to: $wersja\n";
}
}
$sys = new SysInfo();
$sys->getInfo();
#$sys->get_date();
?>
W tym skrypcie PHP mamy klasę SysInfo. Wynikiem działania są informacje o
systemie wyświetlane w konsoli. Mamy dwie funkcje prywatne i jedną publiczną.
Metody prywatne są tu tylko używane wewnątrz klasy SysInfo. Nie są one
przeznaczone do używania poza klasą.
$sys = new SysInfo();
$sys->getInfo();
#$sys->get_date();
Tworzymy instancję klasy SysInfo i wywołujemy dostępną metodę publiczną
getInfo(). Metoda getInfo() używa wewnętrznie prywatnych metod do jej pracy.
Odkomentowanie ostatniego wiersza kodu daje błąd.
Uazz.pl
Strona 14
Metoda przeciążania
Metoda przeciążenia pozwala na tworzenie kilku metod o tej samej nazwie, które
różnią się od siebie typem danych wejściowych.
Czy przeciążanie metody jest dobre? Biblioteka Qt4 daje dobry przykład dla
użytkownika. Klasa QPainter ma trzy metody, aby narysować prostokąt. Ich nazwa to
drawRect(), a ich parametry różnią się. Jedna z nich ma odniesienie do obiektu
prostokąt typu float, inna ma odniesienie do obiektu rectangle typu int i ostatnia ma
cztery parametry, x, y, szerokość, wysokość. Jeśli język C++ jest językiem, w którym
Qt jest rozwijany, nie ma metod przeciążania, twórcy biblioteki będą musieli utworzyć
metody, takie jak drawRectRectF(), drawRectRect(), drawRectXYWH(). Rozwiązanie
z przeciążeniem metody jest bardziej eleganckie.
<?php
class Suma {
public function getSum() {
return 0;
}
public function getSum($x) {
return $x;
}
public function getSum($x, $y) {
return $x + $y;
}
}
$s = new Suma();
echo $s->getSum() . "\n" ;
echo $s->getSum(5) . "\n" ;
echo $s->getSum(3, 4) . "\n" ;
?>
Jest to metoda przeciążania, znamy to z języków, takich jak C#, Java lub C++. Ale to
nie działa w PHP. Po uruchomieniu tego przykładu, otrzymujemy następujący
komunikat o błędzie: 'Fatal error: Cannot redeclare Sum::getSum()' "błąd krytyczny:
nie można zadeklarować Suma::getSum()'. Funkcje PHP mogą przyjmować dowolną
liczbę zmiennych domyślnie.
Do symulacji, metody przeciążenia w PHP, możemy użyć funkcji
func_get_args().
Uazz.pl
Strona 15
<?php
class Suma {
public function getSum() {
$args = func_get_args();
if (empty($args)) return 0;
foreach ($args as $arg) {
$sum += $arg;
}
return $sum;
}
}
$s = new Suma();
echo $s->getSum() . "<br />" ;
echo $s->getSum(5) . "<br />" ;
echo $s->getSum(3, 4) . "<br />" ;
echo $s->getSum(3, 4, 7) . "<br />" ;
?>
Tym razem, skrypt zostanie uruchomiony.
$args = func_get_args();
Funkcja
func_get_args()
zwraca tablicę, obejmującą listę argumentów funkcji.
foreach ($args as $arg) {
$sum += $arg;
}
Przechodzimy przez wszystkie elementy tablicy, a następnie obliczamy sumę.
echo $s->getSum() . "\n" ;
echo $s->getSum(5) . "\n" ;
echo $s->getSum(3, 4) . "\n" ;
echo $s->getSum(3, 4, 7) . "\n" ;
Wywołujemy taką samą nazwę metody z różną liczbą wejść.
Uazz.pl
Strona 16
Konstruktor
Konstruktor jest specjalnym rodzajem metody. Jest ona automatycznie wywoływana,
gdy tworzony jest obiekt. Celem konstruktora jest inicjowanie stanu obiektu. Nazwa
konstruktora w PHP 5 jest 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";
}
}
Uazz.pl
Strona 17
$piosenka = new Piosenka("Malinowy król");
?>
Możemy zmienić nieco poprzedni przykład. Możemy przekazać wartość do
konstruktora.
function __construct($piosenka) {
echo "Piosenka $piosenka jest utworzona \n";
}
Przekazany argument jest przechowywany w zmiennej lokalnej $piosenka.
$ php konstruktor2.php
Piosenka Malinowy król jest utworzona
Teraz mamy wyświetlony tytułu piosenki w konsoli.
W następnym przykładzie możemy zainicjować pola klasy. Inicjacja zmiennych jest
typowym zadaniem dla konstruktorów.
<?php
class Przyjaciel {
private $urodzony;
private $imie;
function __construct($imie, $urodzony) {
$this->imie = $imie;
$this->urodzony = $urodzony;
}
function getInfo() {
echo "Mój przyjaciel $this->imie urodził się w $this->urodzony\n";
}
}
$przyjaciel = new Przyjaciel("Adam", 1976);
$przyjaciel->getInfo();
?>
Mamy klasę Przyjaciel z polami i metodami.
private $urodzony;
private $imie;
Uazz.pl
Strona 18
Mamy dwie zmienne w definicji klasy. Słowo kluczowe
private
jest modyfikatorem
dostępu. Jest to forma hermetyzacji. Słowo kluczowe
private
jest najbardziej
restrykcyjnym modyfikatorem. Pozwala na dostęp tylko obiektowi, w którym
występuje. Więcej na ten temat później.
function __construct($imie, $urodzony) {
$this->imie = $imie;
$this->urodzony = $urodzony;
}
W konstruktorze inicjujemy dwa pola. Zmienna
$this
jest używana do dostępu do
zmiennych obiektu.
$przyjaciel = new Przyjaciel("Adam", 1976);
$przyjaciel->getInfo();
Tworzymy obiekt Przyjaciel z dwoma argumentami. Następnie możemy wywołać
metodę getInfo() obiektu. Do wywołania metody obiektu, możemy użyć operatora -
>.
$ php przyjaciel.php
Mój przyjaciel Adam urodził się w 1976
Uazz.pl
Strona 19
Stałe w klasie
PHP umożliwia tworzenie stałych klasy. Te stałe nie należą do konkretnego obiektu.
Należą one do tej klasy. Umownie stałe są pisane wielkimi literami.
<?php
class Math {
const PI = 3.14159265359;
public function getPI() {
echo self::PI;
}
}
$math = new Math();
echo Math::PI, "\n";
echo $math->getPI(), "\n";
?>
Mamy klasy Math ze stałą PI.
const PI = 3.14159265359;
Słowo kluczowe
const
jest używane do definiowania stałych.
public function getPI() {
echo self::PI;
}
Stałe w klasie są dostępne w ramach metody za pomocą słowa kluczowego
self
, a
następnie przez dwa dwukropki.
echo Math::PI, "\n";
echo $math->getPI(), "\n";
Wyświetlamy stałą PI na konsoli. W pierwszym przypadku mamy stałą wartość
odwołując się do nazwy klasy, a następnie dwa dwukropki i nazwę stałej. Należy
zauważyć, że obiekt nie był potrzebny, aby uzyskać dostęp do stałej. W drugim
przypadku używamy metody obiektu.
Uazz.pl
Strona 20
Słowo kluczowe instanceof
Słowo kluczowe
instanceof
jest używane do określenia czy dany obiekt jest obiektem
danej klasy, lub klasy, która dziedziczy po danej klasie, oraz czy zmienna PHP jest
instancją obiektu pewnej klasy.
<?php
class Kot {}
class Pies {}
class Ptak {}
$objekt = array(new Kot(), new Pies(), new Kot(),
new Ptak(), new Ptak(), new Pies(),
new Pies(), new Kot(), new Ptak()
);
shuffle($objekt);
foreach ($objekt as $object) {
if ($object instanceof Kot) {
echo "To jest Kot <br />";
} elseif ($object instanceof Pies) {
echo "To jest Pies <br />";
} elseif ($object instanceof Ptak) {
echo "To jest Ptak <br />";
}
}
?>
W skrypcie powyżej mamy trzy klasy. Kot, Pies i Ptak. Przechodzimy przez tablicę i
wyświetlamy nazwy klas dla każdej wartości tablicy.
$objekt = array(new Kot(), new Pies(), new Kot(),
new Ptak(), new Ptak(), new Pies(),
new Pies(), new Kot(), new Ptak()
);
Tworzymy tablicę tych obiektów.
shuffle($objekt);
Uazz.pl
Strona 21
Funkcja shuffle losuje kolejność elementów w tablicy. W tym momencie nie wiemy,
jakie klasy są zapisane w tablicy.
if ($object instanceof Kot) {
echo "To jest Kot <br />";
}
Tutaj możemy użyć słowa kluczowego
instanceof
aby dowiedzieć się, jaki jest typ
klasy.
$ php instanceof.php
To jest Ptak
To jest Kot
To jest Kot
To jest Pies
To jest Pies
To jest Kot
To jest Pies
To jest Ptak
To jest Ptak
Dane wyjściowe uruchomionego skryptu.
Uazz.pl
Strona 22
Metoda __toString()
Gdy używamy słowa kluczowego
lub
echo
występującego z instancją obiektu,
to wywoływana jest specjalna metoda
__toString()
. Pokażemy to w poniższym
przykładzie.
<?php
class Kot {
public $imie;
public $wiek;
function __construct($imie, $wiek) {
$this->wiek = $wiek;
$this->imie = $imie;
}
function __toString() {
return "Kot: $this->imie, Wiek: $this->wiek \n";
}
}
$pimpek = new Kot("Pimpek", 6);
$tofik = new Kot("Tofik", 4);
print $pimpek;
echo $tofik;
?>
Mamy klasę Kot z zdefiniowaną specjalną metodą
__toString().
function __toString() {
return "Kot: $this->imie, Wiek: $this->wiek \n";
}
Metoda wyświetla podstawowe informacje o obiekcie.
$pimpek = new Kot("Pimpek", 6);
$tofik = new Kot("Tofik", 4);
Uazz.pl
Strona 23
Tworzymy dwa obiekty klasy Kot.
print $pimpek;
echo $tofik;
I używamy słów kluczowych
lub
echo
.
$ php tostring.php
Kot: Pimpek, Wiek: 6
Kot: Tofik, Wiek: 4
Powyżej wynik działania skryptu.
Uazz.pl
Strona 24
Dziedziczenie
Dziedziczenie jest to sposób, aby nowe klasy były tworzone przy użyciu klas, które już
zostały zdefiniowane. Nowo powstałe klasy są nazywane klasami pochodnymi, tak
nazywane są klasy, które tworzymy na podstawie klasy bazowej. Ważne, jest, że
korzyści wynikające z dziedziczenia to wielokrotne wykorzystanie kodu i zmniejszenie
złożoności programu. Klasy pochodne (potomkowie) mogą zastąpić lub rozszerzyć
funkcjonalność klasy bazowej (przodków).
<?php
class Podstawowa {
function __construct() {
echo " Konstrukcja klasy podstawowej \n";
}
}
class Pochodna extends Podstawowa {
function __construct() {
parent::__construct();
echo " Konstrukcja klasy pochodnej \n";
}
}
$obj1 = new Podstawowa();
$obj2 = new Pochodna();
?>
W tym skrypcie PHP mamy dwie klasy. I klasę pochodną i klasę podstawową. Klasa
Pochodna dziedziczy z klasy Podstawowa.
class Pochodna extends Podstawowa {
W PHP, używamy słowa kluczowego
extends
do tworzenia relacji dziedziczenia.
function __construct() {
parent::__construct();
echo " Konstrukcja klasy pochodnej \n";
}
W konstruktorze klasy Pochodna wywołujemy konstruktora rodzica. Używamy słowa
parent
, a następnie dwa dwukropki i metodę
__construct()
. Konstruktor klasy
bazowej musi być jawnie wywołany.
Uazz.pl
Strona 25
$obj1 = new Podstawowa();
$obj2 = new Pochodna();
Możemy utworzyć bazy podstawowe i klasy pochodne.
$ php klasy.php
Konstrukcja klasy podstawowej
Konstrukcja klasy podstawowej
Konstrukcja klasy pochodnej
To dane wyjściowe skryptu PHP.
Przykład bardziej skomplikowanego skryptu.
<?php
abstract class Istota {
protected $jestZywy = true;
public function jestZywy() {
if ($this->jestZywy) {
echo "Istota jest żywa\n";
} else {
echo "Istota jest nie żywa\n";
}
}
public function kill() {
$this->jestZywy = false;
}
}
abstract class Zwierze extends Istota {
protected $wiek;
public function __construct($wiek) {
$this->wiek = $wiek;
}
protected function setAge($wiek) {
$this->wiek = $wiek;
}
public function getAge() {
return $this->wiek;
}
Uazz.pl
Strona 26
}
class Kot extends Zwierze {
private $imie;
public function __construct($imie, $wiek) {
$this->ime = $imie;
parent::__construct($wiek);
}
public function getName() {
return $this->imie;
}
}
$kot = new Kot("Tofik", 4);
$kot->jestZywy();
echo $kot->getName() . " ma " . $kot->getAge() . " lat(a)\n";
$kot->kill();
$kot->jestZywy();
?>
Użyliśmy tutaj kilka nowych koncepcji. W przykładowym kodzie mamy trzy klasy.
Istota, Zwierze i Kot. Klasa Zwierze dziedziczy z klasy Istota. Klasa Kot dziedziczy z
klasy Zwierze. Klasy dziedziczą metody i elementy danych, które nie zostały
zadeklarowane, jako prywatne.
abstract class Istota {
Klasa Istota jest zadeklarowana za pomocą słowa
abstract
. Słowo kluczowe
abstract
zakazuje wystąpienia klasy. Nie ma sensu aby utworzyć wystąpienie klasy
Istota.
protected $jestZywy = true;
Właściwość (zmienna, pole) $jestZywy jest zadeklarowana za pomocą słowa
protected
. Właściwości są dostępne tylko dla klas, w których zostały zadeklarowane
oraz w klasach potomnych.
abstract class Zwierze extends Istota {
Klasa Animal jest również uznana za abstrakcyjną. Dziedziczy z klasy Istota. W tym
celu możemy użyć słowa kluczowego
extends
. Klasa Zwierze jest potomkiem.
Dziedziczy metody i zmienne klasy bazowej Istota.
class Kot extends Zwierze {
Uazz.pl
Strona 27
Klasa Kot dziedziczy z klasy Zwierze. Dziedziczy z klasy Zwierze i pośrednio z klasy Istota.
Ta klasa nie jest zadeklarowana, jako abstrakcyjna, co oznacza, możemy używać jej
instancję.
parent::__construct($wiek);
W konstruktorze klasy Kot, wywołujemy konstruktor rodzica przy użyciu słowa
parent
, następnie przez dwa dwukropki i metodę
__ construct ()
. Konstruktor
klasy dominującej musi być wywołany jawnie.
$kot = new Kot("Tofik", 4);
$kot->jestZywy();
echo $kot->getName() . " ma " . $kot->getAge() . " lat(a)\n";
$kot->kill();
$kot->jestZywy();
Tworzymy nowy obiekt Kot. Tofik, 4 lat. Następnie wywołujemy funkcje na obiekcie
Tofik. Należy zwrócić uwagę na wykorzystanie metod, które nie zostały utworzone w
klasie Kot, ale dziedziczone z klas nadrzędnych.
$ php dziedziczenie.php
Istota jest żywa
ma 4 lat(a)
Istota jest nie żywa
Dane wyjściowe skryptu.
Uazz.pl
Strona 28
Klasy abstrakcyjne i metody
PHP 5 wprowadza klasy i metody abstrakcyjne. Nie można utworzyć wystąpienia
klasy abstrakcyjnej. Jeśli Klasa zawiera, co najmniej jedną metoda abstrakcyjna, musi
być zadeklarowana także, jako abstrakcyjna. Metody abstrakcyjne nie mogą być
implementowane. Kiedy możemy dziedziczyć z klasy abstrakcyjnej, wszystkie metody
abstrakcyjne muszą być zaimplementowane w klasie pochodnej. Ponadto metody te
muszą być zadeklarowane z tą samą ograniczoną widocznością.
Unlike interfaces, abstract classes may have methods with full implementation and
may also have defined member fields. So abstract classes may provide a partial
implementation. Programmers often put some common functionality into abstract
classes. And these abstract classes are later subclassed to provide more specific
implementation. For example, the Qt graphics library has a QAbstractButton, which
is the abstract base class of button widgets, providing functionality common to
buttons. Buttons Q3Button, QCheckBox, QPushButton, QRadioButton, and
QToolButton inherit from this base abstract class.
W przeciwieństwie do interfejsów (interfaces) klasy abstrakcyjne mogą mieć
metody z pełną implementacją i mogą również mieć zdefiniowane właściwości
(zmienne). Więc klasy abstrakcyjne mogą zapewnić częściową implementacje.
Programiści często umieszczają niektóre typowe funkcje w klasach abstrakcyjnych.
Klasy abstrakcyjne zapewniają podklasom określone implementacje. Na przykład
biblioteka graficzna Qt ma QAbstractButton, która jest abstrakcyjną klasą z
podstawowymi wzorami przycisków, zapewniając funkcje wspólne dla przycisków.
Przyciski Q3Button, QCheckBox, QPushButton, QRadioButton i QToolButton
dziedziczą z tej podstawowej klasy abstrakcyjnej.
Formalnie mówiąc, abstrakcyjne klasy są używane do wymuszania protokołu.
Protokół to zestaw czynności, które muszą obsługiwać wszystkie obiekty wykonawcze.
<?php
abstract class Rysunek {
protected $x = 0;
protected $y = 0;
public abstract function obszar();
public function getCoordinates() {
Uazz.pl
Strona 29
echo "\$x is $this->x\n";
echo "\$y is $this->y\n";
}
}
class Kolo extends Rysunek {
private $promien;
public function __construct($x, $y, $r) {
$this->promien = $r;
$this->x = $x;
$this->y = $y;
}
public function obszar() {
return $this->promien * $this->promien * pi();
}
public function __toString() {
return " Koło, w x: $this->x, y: $this->y, promień: $this->promien";
}
}
$o = new Kolo(12, 45, 22);
echo "$o \n";
echo " Obszar koła: " . $o->obszar() . "\n";
echo $o->getCoordinates();
?>
W naszym skryptcie PHP mamy abstrakcyjną klasę podstawową Rysunek. Klasa
definiuje dwa pola (właściwości, zmienne), definiuje jedną metodę i deklaruje, jedną
metodę. Jedna z metod jest abstrakcyjna, druga jest w pełni implementowana. Klasa
Rysunek jest abstrakcyjna, ponieważ nie możemy rysować. Mamy narysować okrąg,
kropkę lub kwadrat. Klasa Rysunek ma pewne typowe funkcje dla obiektów, które
można wyciągnąć.
class Kolo extends Rysunek {
Klasa Kolo jest podklasą klasy Rysunek. Ona musi implementować abstrakcyjne
metody.
$ php abstrakt.php
Koło, w x: 12, y: 45, promień: 22
Obszar koła: 1520.5308443375
$x is 12
$y is 45
Uazz.pl
Strona 30
Dane wyjściowe skryptu.
Uazz.pl
Strona 31
Interfejsy
Pilot zdalnego sterowania jest interfejsem pomiędzy widzem i telewizorem. Jest to
interfejs do elektronicznych urządzeń. Protokół dyplomatyczny prowadzi wszystkie
działania w dyplomacji. Przepisy ruchu drogowego są to reguły, które muszą
przestrzegać kierowcy, rowerzyści i piesi. Interfejsy programowania są analogiczne w
poprzednich przykładach.
Interfaces are:
Interfejsy są:
APIs
Contracts
Obiekty wchodzą w interakcje ze światem zewnętrznym za pomocą metod. Faktyczna
implementacja nie jest ważna dla programisty, lub też może być to dla niego tajne.
Firma może sprzedawać biblioteki i nie chce ujawniać rzeczywistych realizacji.
Programista może wywołać metodę maximize() okna narzędzi GUI, ale nie wie nic na
temat jak ta metoda jest implementowana. Z tego punktu widzenia interfejsy są to
metody, za pomocą, których obiekty wchodzą w interakcję ze światem zewnętrznym,
nie narażając zbytnio ich wewnętrzne funkcjonowanie.
Z drugiego punktu widzenia interfejsy są jedynie zbiorem ściśle określonych reguł..
Jeżeli są one uzgodnione, muszą one być stosowane. Są one używane do
projektowania architektury aplikacji. One pomagają w zorganizowaniu kodu.
Interfejsy są to całkowicie abstrakcyjne typy. One są deklarowane przy użyciu słowa
kluczowego
interface
. Interfejsy może mieć tylko zadeklarowane metody. Wszystkie
metody zadeklarowane w interfejsie muszą być publiczne. One nie moją pełnej
implementacji metody, ani pola (zmienne). Klasy PHP mogą implementować
dowolną liczbę interfejsów. Interfejs można rozszerzać dowolną liczbą interfejsów.
Klasa, która implementuje interfejs musi implementować wszystkie metody
interfejsu.
Interfejsy są używane do symulowania wielokrotnego dziedziczenia. Klasy PHP
można rozszerzyć tylko jedną klasą. Klasy PHP mogą zaimplementować wiele
interfejsów. W wielokrotnym dziedziczeniu przy użyciu interfejsów nie chodzi o
Uazz.pl
Strona 32
dziedziczenie metod i zmiennych. Chodzi o dziedziczenie pomysłów lub umów, które
są opisane przez interfejsy.
Istnieje jedna istotna różnica między interfejsem i klasą abstrakcyjną. Klasy
abstrakcyjne dostarczają częściową implementację dla klas, które są związane w
hierarchii dziedziczenia. Interfejsy z drugiej strony mogą być implementowane przez
klasy, które nie są powiązane ze sobą. Na przykład mamy dwa przyciski. Klasyczny
przycisk i okrągły przycisk. Oba dziedziczą z klasy abstrakcyjnej przycisk, która
zapewnia pewne typowe funkcje dla wszystkich przycisków. Innym przykładem mogą
być klasy Database i SignIn. Nie są one powiązane ze sobą. Możemy zastosować
interfejs ILoggable, który miał zmusić ich do utworzenia metody do logowania.
<?php
interface IInfo {
public function do_inform();
}
class Some implements IInfo {
public function do_inform() {
echo "To jest przykładowa klasa\n";
}
}
$sm = new Some();
$sm->do_inform();
?>
Jest to prosty skrypt PHP, demonstrujący interfejs.
interface IInfo {
public function do_inform();
}
Jest to interfejs
IInfo
. Deklaracja metody do_inform().
class Some implements IInfo {
Używamy słowa
implements
do implementacji interfejsu.
public function do_inform() {
echo " To jest przykładowa klasa \n";
}
Uazz.pl
Strona 33
Klasa dostarcza implementację metody do_inform().
W następnym przykładzie pokazano, jak klasa może zaimplementować wiele
interfejsów.
<?php
interface Device {
public function switch_on();
public function switch_off();
}
interface Volume {
public function volume_up();
public function volume_down();
}
interface Pluggable {
public function plug_in();
public function plug_off();
}
class CellPhone implements Device, Volume, Pluggable {
public function switch_on() { echo " Włączanie \n"; }
public function switch_off() { echo " Wyłączanie \n"; }
public function volume_up() { echo "Głośniej\n"; }
public function volume_down() { echo "Ciszej\n"; }
public function plug_in() { echo "Podłączanie\n"; }
public function plug_off() { echo "Odłączanie\n"; }
}
$o = new CellPhone();
$o->switch_on();
$o->volume_up();
$o->plug_in();
?>
Mamy klasę CellPhone, która dziedziczy z trzech interfejsów.
class CellPhone implements Device, Volume, Pluggable {
Klasy implementuje wszystkie trzy interfejsy, które są przedzielone przecinkiem.
Klasa CellPhone musi implementować wszystkie metody ze wszystkich trzech
interfejsów.
$ php interfejs.php
Włączanie
Uazz.pl
Strona 34
Głośniej
Podłączanie
Uruchamianie skryptu PHP.
W następnym przykładzie pokazano, jak rozszerzyć interfejsy przez wiele innych
interfejsów.
<?php
interface IInfo {
public function do_inform();
}
interface IVersion {
public function get_version();
}
interface ILog extends IInfo, IVersion {
public function do_log();
}
class DBConnect implements ILog {
public function do_inform() {
echo "To jest klasa DBConnect\n";
}
public function get_version() {
echo "Wersja 1.02\n";
}
public function do_log() {
echo "Logowanie\n";
}
public function connect() {
echo "Łączenie z bazą danych\n";
}
}
$db = new DBConnect();
$db->do_inform();
$db->get_version();
$db->do_log();
$db->connect();
?>
W tym skrypcie PHP możemy zdefiniować trzy interfejsy. Rozszerzenie interfejsów
pozwala nam zorganizować je.
Uazz.pl
Strona 35
interface ILog extends IInfo, IVersion {
public function do_log();
}
Interfejs ILog rozszerza inne dwa interfejsy.
public function do_inform() {
echo " To jest klasa DBConnect \n";
}
Klasa DBConnect implementuje metodę do_inform(). Metoda ta została
odziedziczona przez interfejs ILog, który implementuje klasę.
Uazz.pl
Strona 36
Polimorfizm
Polimorfizm jest to proces, który używa operator lub funkcję w różny sposób dla
różnych danych wejściowych. W praktyce polimorfizm oznacza, że jeśli Klasa B
dziedziczy z klasy A, nie musi dziedziczyć wszystkiego z klasy A; może zrobić kilka
rzeczy z tej klasy.
Ogólnie rzecz biorąc polimorfizm jest to zdolność do tworzenia kilku obiektów z
określonych klas bazowych. Technicznie rzecz biorąc jest to zdolność
przedefiniowania metod klasy pochodnej. Polimorfizm dotyczy stosowania określonej
implementacji interfejsu lub bardziej ogólnie klasy podstawowej.
<?php
abstract class Ksztalt {
private $x = 0;
private $y = 0;
public abstract function area();
}
class Prostokat extends Ksztalt {
function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
function area() {
return $this->x * $this->y;
}
}
class Kwadrat extends Ksztalt {
function __construct($x) {
$this->x = $x;
}
function area() {
return $this->x * $this->x;
}
}
$shapes = array(
new Kwadrat(5),
new Prostokat(12, 4),
new Kwadrat(8)
);
foreach ($shapes as $shape) {
echo $shape->area() . "\n";
Uazz.pl
Strona 37
}
?>
W powyższym skrypcie PHP mamy klasę abstrakcyjną Kształt. Ta klasa przemienia
się w dwie klasy podrzędne, Prostokat i Kwadrat. Oba rozwiązania zapewniają
realizację metody area(). Polimorfizm przynosi elastyczności i skalowalność
systemów OOP.
Uazz.pl
Strona 38
Programowanie obiektowe II
W tym rozdziale kursu PHP nadal opisujemy OOP w języku PHP.
Słowa kluczowe static
Możemy zadeklarować właściwości klasy i metody jako
static
(statyczne). Statyczne
właściwości i metody nie należą do instancji klasy. Należą one do samej klasy. Są one
dostępne przez operator (::).
<?php
class Sys {
public static function println($string) {
echo "$string\n";
}
}
Sys::println("PHP");
Sys::println("PERL");
Sys::println("Python");
Sys::println("Pike");
?>
W powyższym skrypcie PHP mamy metodę statyczną (static) println(). Wyświetla
ciąg i przechodzi do nowej linii. W tym przykładzie wywodzi się z języka Java.
Sys::println("PHP");
Nie potrzebujemy w obiekcie wywoływać metody println(). Wywołujemy metody
statyczne (static) określając nazwę klasy, a następnie używamy operatora podwójny
dwukropek i jej nazwę.
$ php static1.php
PHP
PERL
Python
Pike
Powyżej dane wyjściowe skryptu.
Uazz.pl
Strona 39
<?php
class Math {
public static $PI = 3.14159265359;
}
echo Math::$PI . "\n";
?>
I teraz mamy przykład ze zmienną statyczną.
echo Math::$PI . "\n";
Możemy uzyskać dostęp do zmiennej określając nazwę klasy, i następnie operator
zakresu i nazwę zmiennej.
Uazz.pl
Strona 40
Słowo kluczowe final
Jeżeli metoda zostanie zdefiniowana z użyciem słowa kluczowego
final
, to nie będzie
mogła zostać nadpisana w żadnej podklasie. Użycie słowa kluczowego
final
jest
kwestią projektowania aplikacji. Niektóre klasy nie powinny być rozszerzane i
niektóre metody nie powinny być nadpisane. To zachowanie jest egzekwowane przez
słowo
final
.
<?php
class Podstawowa {
final function say() {
echo " Klasa podstawowa ";
}
}
class Pochodna extends Podstawowa {
function say() {
echo " Klasa pochodna ";
}
}
?>
Ten skrypt PHP nie uruchomi się. Możemy dostać błąd " Cannot override final
method Base::say()".
<?php
final class Math {
static function getPI() {
return 3.141592;
}
}
class DerivedMath extends Math {
function say() {
echo "DerivedMath class";
}
}
?>
Uazz.pl
Strona 41
W poprzednim skrypcie PHP mamy prototyp klasy podstawowej Math. Jedynym
celem tej klasy jest zapewnienie kilka pomocnych metod i stałych. (W naszym
przypadku mamy tylko jedną metodę). Nie jest tworzona jako rozszerzona. Aby
uniknąć nadpisywania metod przez innych programistów, aby nie mogli dziedziczyć z
tej klasy, twórcy przygotowali klasę, jako
final
. Jeśli ty spróbujesz uruchomić ten
skrypt PHP, otrzymasz następujący komunikat o błędzie: "Fatal error: Class
DerivedMath may not inherit from final class (Math)". ("błąd krytyczny: Klasa
DerivedMath nie może dziedziczyć z klasy final (Math)".)
Uazz.pl
Strona 42
Deep copy vs shallow copy
Kopiowanie danych jest ważnym zadaniem w programowaniu. Obiekt jest to złożony
typ danych w OOP. Pola w obiekcie mogą być przechowywane przez wartość lub przez
odwołanie. Kopiowanie można wykonać na dwa sposoby.
Płytkie kopiowanie (shallow copy ) kopiuje wszystkie wartości i odwołania do
nowego wystąpienia. Dane do którego wskazuje odwołanie nie są kopiowane; tylko
wskaźnik jest kopiowany. Nowe odniesienia są skierowane do oryginalnych obiektów.
Żadne zmiany pól odniesienia nie wpływają na oba obiekty.
Głębokie kopie (deep copy) kopiują wszystkie wartości do nowego wystąpienia. W
przypadku pól, które są przechowywane, jako głębokie kopie wykonuje głębokie kopii
danych, do którego istnieje odwołanie. Nowa kopia obiektu tworzona jest przez
odwołanie. A wskaźnik do nowo utworzonego obiektu. Zmiany w tym obiekcie nie
wpłyną na inne kopie obiektu. Głębokie kopie w pełni replikują obiekty.
In PHP, we have a
copy
keyword, which performs a shallow copy by default. It calls
the object's
__clone()
method. We can implement the method to create our custom
deep copy. In PHP 5, all objects are assigned by reference.
W PHP mamy słowo kluczowe
copy
, które wykonuje płytkie kopię domyślnie. To
wywołuje metodę obiektu
__clone()
. Używamy tę metodę, aby utworzyć
egzemplarz, przez głębokie kopiowanie. W PHP 5 wszystkie obiekty są przypisane
przez referencję.
Następne dwa przykłady wykonają płytkie i głębokie kopie obiektów.
<?php
class Objekt {
public $id;
public $rozmiar;
public $kolor;
function __construct($id, $rozmiar, $kolor) {
$this->id = $id;
$this->rozmiar = $rozmiar;
$this->kolor = $kolor;
}
}
Uazz.pl
Strona 43
class Kolor {
public $czerwony;
public $zielony;
public $niebieski;
function __construct($czerwony, $zielony, $niebieski) {
$this->czerwony = $czerwony;
$this->zielony = $zielony;
$this->niebieski = $niebieski;
}
}
$kolor = new Kolor(23, 42, 223);
$object1 = new Objekt(23, "maly", $kolor);
$object2 = clone $object1;
$object2->id++;
$object2->kolor->czerwony = 255;
$object2->rozmiar = "duzy";
print_r($object1);
print_r($object2);
?>
W powyższym skrypcie PHP definiujemy dwa obiekty niestandardowe. Obiekt i Kolor.
Obiekt będzie miał odwołanie do obiektu Kolor.
$kolor = new Kolor(23, 42, 223);
Tworzymy nową instancję obiektu Kolor.
$object1 = new Objekt(23, "maly", $kolor);
Tworzona jest instancja klasy Objekt. Wystąpienie obiektu Kolor przechodzi do jego
konstruktora.
$object2 = clone $object1;
Wykonujemy płytkie kopie obiektu.
$object2->id++;
$object2->kolor->czerwony = 255;
$object2->rozmiar = "duzy";
Tutaj możemy modyfikować pola sklonowanego obiektu. Zwiększamy identyfikator,
zmieniamy częściowo czerwony kolor obiektu i zmieniamy rozmiar na "duzy".
print_r($object1);
print_r($object2);
Uazz.pl
Strona 44
Używamy funkcji
print_r()
aby porównać wyniki.
$ php plytkakopia.php
Objekt Object
(
[id] => 23
[rozmiar] => maly
[kolor] => Kolor Object
(
[czerwony] => 255
[zielony] => 42
[niebieski] => 223
)
)
Objekt Object
(
[id] => 24
[rozmiar] => duzy
[kolor] => Kolor Object
(
[czerwony] => 255
[zielony] => 42
[niebieski] => 223
)
)
Widzimy, że identyfikatory są różne. 23 vs 24. Rozmiar jest inny. "mały" vs "duzy".
Ale kolor czerwony dla obiektu jest taki sam dla obu wystąpień. 255. Zmiana wartości
pola obiektu sklonowanego nie miał wpływu na oryginalny obiekt. Zmiana pola
odwołania wpłynęło także na oryginalny obiekt. Innymi słowy oba obiekty odnoszą się
do tego samego koloru obiektu w pamięci.
Aby zmienić to zachowanie, zrobimy głęboką kopię poniżej.
Uazz.pl
Strona 45
<?php
class Objekt {
public $id;
public $rozmiar;
public $kolor;
function __construct($id, $rozmiar, $kolor) {
$this->id = $id;
$this->rozmiar = $rozmiar;
$this->kolor = $kolor;
}
function __clone() {
$czerwony = $this->kolor->czerwony;
$zielony = $this->kolor->zielony;
$niebieski = $this->kolor->niebieski;
$this->kolor = new Kolor($czerwony, $zielony, $niebieski);
}
}
class Kolor {
public $czerwony;
public $zielony;
public $niebieski;
function __construct($czerwony, $zielony, $niebieski) {
$this->czerwony = $czerwony;
$this->zielony = $zielony;
$this->niebieski = $niebieski;
}
}
$kolor = new Kolor(23, 42, 223);
$object1 = new Objekt(23, "maly", $kolor);
$object2 = clone $object1;
$object2->id++;
$object2->kolor->czerwony = 255;
$object2->rozmiar = "duzy";
print_r($object1);
print_r($object2);
?>
W tym skrypcie PHP zaimpletowaliśmy metodę
__clone().
function __clone() {
$red = $this->kolor->czerwony;
$green = $this->kolor->zielony;
$blue = $this->kolor->niebieski;
Uazz.pl
Strona 46
$this->kolor = new Kolor($czerwony, $zielony, $niebieski);
}
Wewnątrz metody
__clone()
kopiujemy pola czerwony, zielony i niebieski i
tworzymy nowy obiekt Kolor. Teraz pole $kolor wskazuje na inny kolor obiektu.
$ php glebokakopia.php
Objekt Object
(
[id] => 23
[rozmiar] => maly
[kolor] => Kolor Object
(
[czerwony] => 23
[zielony] => 42
[niebieski] => 223
)
)
Objekt Object
(
[id] => 24
[rozmiar] => duzy
[kolor] => Kolor Object
(
[czerwony] => 255
[zielony] => 42
[niebieski] => 223
)
)
Teraz kolor czerwony obiektu Kolor nie jest taki sam. Oryginalny obiekt zachował
swoją poprzednią wartość 23.
Uazz.pl
Strona 47
Wyjątki
Wyjątki są zaprojektowane do obsługi występowania wyjątków, są to specjalne
warunki, które zmieniają tok normalnego wykonywania programu. Wyjątki są
wywoływane, wyrzucane lub inicjowane.
Podczas realizacji naszej aplikacji wiele rzeczy może pójść źle. Dysk może zostać
zapełniony i nie możemy zapisać naszego pliku. Połączenie z Internetem może zostać
przerwane i nasza aplikacja próbuje połączyć się z witryną. Wszystko to może
doprowadzić do awarii naszej aplikacji. Aby zapobiec, takim przypadkom, my musimy
radzić sobie z wszystkimi możliwymi błędami, które mogą wystąpić. Do tego możemy
użyć obsługi wyjątków.
Wyjątki zostały dopiero niedawno wprowadzone do języka PHP 5. Większość błędów
PHP nadal używa starego raportowanie błędów a nie wyjątki. Funkcja
set_error_handler()
możemy użyć do obsługi błędów w skrypcie.
<?php
set_error_handler("error_handler");
function error_handler($errno, $errstring, $errfile, $line, $trace) {
throw new ErrorException($errstring, $errno, 0, $errfile, $line);
}
try {
$a = 0;
$b = 32;
$c = $b / $a;
} catch(ErrorException $e) {
echo " Wystąpił błąd \n";
echo $e->getMessage(), "\n";
}
?>
W powyższym skrypcie PHP celowo podzieliliśmy liczbę przez zero. Prowadzi to do
błędu. Ten błąd nie jest wyjątkiem i nie zostaje wychwycony przez słowo kluczowe
catch
.
set_error_handler("error_handler");
Funkcja
set_error_handler()
ustawia funkcję obsługi błędów zdefiniowanych
przez użytkownika.
Uazz.pl
Strona 48
function error_handler($errno, $errstring, $errfile, $line, $trace) {
throw new ErrorException($errstring, $errno, 0, $errfile, $line);
}
Wewnątrz funkcji
set_error_handler()
wrzucamy
ErrorException
. Wyjątek ten
później zostanie przechwycony przez słowo kluczowe
catch
.
try {
$a = 0;
$b = 32;
$c = $b / $a;
}
Kod, który sprawdzamy przed błędem jest umieszczany wewnątrz bloku po słowie
kluczowym
try
.
} catch(Exception $e) {
echo $e->getMessage();
}
Słowo kluczowe
catch
jest używane do przechwycenia wyjątku, który miał miejsce.
Aby dowiedzieć się więcej, możemy wywołać metodę
getMessage()
na obiekcie
wyjątku.
$ php zerodzielenie.php
Wystąpił błąd
Division by zero
Powyżej wynik działania naszego skryptu.
Exception
jest klasą bazową dla wszystkich wyjątków. Możemy stworzyć własne
wyjątki z tej klasy podstawowej.
<?php
define("LIMIT", 333);
class BigValueException extends Exception {
public function __construct($message) {
parent::__construct($message);
}
}
$a = 34325;
try {
if ($a > LIMIT) {
Uazz.pl
Strona 49
throw new BigValueException("Przekroczono maksymalną wartość
dozwoloną \n");
}
} catch (BigValueException $e) {
echo $e->getMessage();
}
?>
Powiedzmy, że mamy sytuację, w której nie możemy poradzić sobie z dużymi cyframi.
define("LIMIT", 333);
Liczby większe od tej stałej uznawane są za "duże" przez nasz skrypt PHP.
class BigValueException extends Exception {
We have a BigValueException class. This class derives from the
Exception
class
through the
extends
keyword.
Mamy klasę BigValueException. Klasa ta wywodzi się z klasy
Exception
poprzez
słowo kluczowe
extends
.
public function __construct($message) {
parent::__construct($message);
}
Wewnątrz konstruktora możemy wywołać Konstruktor rodzica.
if ($a > LIMIT) {
throw new BigValueException("Przekroczono maksymalną wartość dozwoloną
\n");
}
Jeśli wartość jest większa niż limit, rzucamy nasze niestandardowe wyjątek.
Podajemy wyjątek komunikat "Przekroczono maksymalną wartość dozwoloną".
} catch (BigValueException $e) {
echo $e->getMessage();
}
Przechwytujemy wyjątek i wyświetlamy go na konsoli.
Uazz.pl
Strona 50
Konstruktor przeciążenia
Konstruktor przeciążenia nie jest obsługiwany w języku PHP. Innymi słowy każda
klasa może mieć tylko jeden Konstruktor zdefiniowany. Wielu programistów, zna,
rozwiązania z języków Java czy C# i szuka podobnych funkcji w PHP. Istnieją dwa
sposoby, aby sobie z tym poradzić.
Pierwsze rozwiązanie jest oparte na funkcji
func_get_args()
. Drugie rozwiązanie
wykorzystuje factory pattern (wzorzec Fabryka).
<?php
class Ksiazka {
private $tytul = " nie określono ";
private $autor = " nie określono ";
private $rok = " nie określono ";
public function __construct() {
$args = func_get_args();
foreach(array("tytul", "autor", "rok") as $item)
{
if(empty($args)) {
break;
}
$this->$item = array_shift($args);
}
}
public function __toString() {
return "Autor: $this->autor\nTytuł: $this->tytul\nWydano: $this-
>rok\n\n";
}
}
$ksiazka1 = new Ksiazka("Barry Burd", "Java for Dummies");
echo $ksiazka1;
$ksiazka2 = new Ksiazka("Paul Wilton", "JavaScript", 2010);
echo $ksiazka2;
?>
W skrypcie powyżej mamy klasę Ksiazka. Możemy utworzyć wystąpienia klasy 2 i 3
parametrami.
private $tytul = " nie określono ";
private $autor = " nie określono ";
Uazz.pl
Strona 51
private $rok = " nie określono ";
Mamy zdefiniowane trzy pola. Ich wartość początkowa jest "nie określona".
$args = func_get_args();
Funkcja func_get_args() zwraca tablicę zawierający listę argumentów funkcji. Więc
chodzi o to: kod wewnątrz konstruktora jest dynamiczny, to zależy od argumentów
przekazywanych do niego.
foreach(array("tytul", "autor", "rok") as $item)
Przechodzimy przez wszystkie pola(zmienne) za pomocą słowa kluczowego
foreach.
$this->$item = array_shift($args);
Jednym z najbardziej podstawowych zadań konstruktorów jest zainicjować pola
klasy. Odbywa się to w powyższej linii kodu. Funkcja
array_shift ()
usuwa pierwszy
element z tablicy i zwraca go.
$ksiazka1 = new Ksiazka("Barry Burd", "Java for Dummies");
…
$ksiazka2 = new Ksiazka("Paul Wilton", "JavaScript", 2010);
Mamy dwa różne konstruktory. Pierwszy ma 2 parametry, drugi 3.
$ php konstruktor.php
Autor: Java for Dummies
Tytuł: Barry Burd
Wydano: nie określono
Autor: JavaScript
Tytuł: Paul Wilton
Wydano: 2010
Jest to wynik działania skryptu.
Uazz.pl
Strona 52
W następnym przykładzie kodu Konstruktor przeciążenia symuluje przy użyciu
wzorca Fabryki. Fabryka abstrakcyjna (ang. Abstract Factory) jest to jeden z
kreacyjnych wzorców projektowych (obiektowy), którego celem jest dostarczenie
interfejsu do tworzenia różnych obiektów jednego typu (tej samej rodziny) bez
specyfikowania ich konkretnych klas. Umożliwia jednemu obiektowi tworzenie
różnych, powiązanych ze sobą, reprezentacji podobiektów określając ich typy podczas
działania programu. (Wikipedia)
<?php
class Kot {
private $imie = "unspecified";
private $wiek = "unspecified";
public static function withName($imie) {
$kot = new Kot();
$kot->imie = $imie;
return $kot;
}
public static function withAge($wiek) {
$kot = new Kot();
$kot->wiek = $wiek;
return $kot;
}
public static function fullCat($imie, $wiek) {
$kot = new Kot();
$kot->imie = $imie;
$kot->wiek = $wiek;
return $kot;
}
public function __toString() {
return "Imie: $this->imie, Wiek: $this->wiek\n";
}
}
$cici = Kot::withName("Miau");
echo $cici;
$missy = Kot::withAge(8);
echo $missy;
$tofik = Kot::fullCat("Tofik", 5);
echo $tofik;
?>
Uazz.pl
Strona 53
W powyższym skrypcie PHP mamy klasę Kot typu wzorzec fabryka. Posiada trzy
różne funkcje statyczne. Każda z nich zwraca obiekt kot.
private $name = "unspecified";
private $age = "unspecified";
Mamy dwa pola. Ich wartość początkowa jest "nieokreślona" (unspecified).
public static function withName($imie) {
$kot = new Kot();
$kot->imie = $imie;
return $kot;
}
Tutaj jest funkcja withName(). Ta funkcja tworzy instancję klasy Kot. Ustawia pole
i zwraca obiekt.
$cici = Kot::withName("Cici");
echo $cici;
Tworzymy wystąpienie cat z jednej z metod fabryki. Funkcja echo obiektu. np.
wywołanie metody
__toString()
klasy.
$ php factory.php
Name: Cici, Age: unspecified
Name: unspecified, Age: 6
Name: Lucky, Age: 4
Dane wyjściowe skryptu.
W tej części kursu PHP kontynuowaliśmy dyskusję na temat programowania
obiektowego w PHP.