1
Podstawy programowania II
dr inż. Paweł Róg
2
Zagadnienia
■
Podstawy programowania obiektowego
Klasy i obiekty.
Pola i metody.
Dostęp do składowych, hermetyzacja.
Konstruktory i destruktory.
Typy argumentów funkcji i metod.
Dziedziczenie.
■
Zagadnienia zaawansowane
Pola i metody statyczne.
3
Klasa
■
Definicja klasy w języku PHP5
class
nazwa_klasy
{
// ciało klasy
}
Klasa jest to złożony typ będący opisem (definicją) pól
i metod obiektów (opis zbioru wszystkich obiektów
mających wspólną strukturę i zachowanie).
Klasa jest to złożony typ będący opisem (definicją) pól
i metod obiektów (opis zbioru wszystkich obiektów
mających wspólną strukturę i zachowanie).
4
Obiekt
■
Tworzenie obiektu w PHP5
$nazwa_zmiennej =
new
nazwa_klasy();
Obiekt jest konkretyzacją (instancją) danej klasy
i wypełnieniem wzorca, jakim jest klasa, określonymi
danymi. Obiekt posiada tożsamość, stan i zachowanie.
Obiekt jest konkretyzacją (instancją) danej klasy
i wypełnieniem wzorca, jakim jest klasa, określonymi
danymi. Obiekt posiada tożsamość, stan i zachowanie.
5
Pola
■
Stan obiektu jest określony przez wartości pól
obiektu. Pola obiektu to zmienne przechowywane
wewnątrz obiektu.
class Zarowka {
private $zapalona
;
}
6
Metody
■
Zachowanie obiektu jest określone przez
metody. Metody są funkcjami zdefiniowanymi
wewnątrz klasy.
class Zarowka {
private $zapalona;
public function zapal() {
$this->zapalona = True;
}
}
7
Hermetyzacja
■
Poziomy dostępu
public – składowa klasy jest dostępna z dowolnego
miejsca programu. Metody są domyślnie publiczne,
chyba, że programista zdecyduje inaczej.
protected – składowa klasy jest dostępna w danej
klasie i jej klasach pochodnych.
private – składowa klasy jest dostępna tylko w klasie,
w której została zdefiniowana.
Hermetyzacja pozwala na ukrycie pewnych danych
i funkcji
obiektu
przed
bezpośrednim
dostępem
z zewnątrz.
Hermetyzacja pozwala na ukrycie pewnych danych
i funkcji
obiektu
przed
bezpośrednim
dostępem
z zewnątrz.
8
Dostęp do składowych
■
Aby uzyskać dostęp do składowych klasy, należy
posłużyć się operatorem -> (minus i znak
większości, bez spacji)
class prosta {
public
$publiczna;
}
function test() {
$obiekt = new prosta();
$obiekt
->
publiczna = 123;
print $obiekt
->
publiczna;
}
9
Dostęp do składowych
■
Oczywiście z zewnątrz klasy możliwy jest jedynie
dostęp do składowych publicznych, dlatego
w przypadku poniższego kodu otrzymamy błąd:
class prosta {
private
$prywatna;
}
function test() {
$obiekt = new prosta();
$obiekt->prywatna = 123; //
błąd !!!
print $obiekt->prywatna; //
błąd !!!
}
10
Wynik działania skryptu
Fatal error: Cannot access private property prosta::
$prywatna in C:\wamp\www\skrypty\prosta.php on
line 8
11
Dostęp do składowych
class SzukamGuza {
public
$problem;
// nie ustawiać
// na True !!!
public function bum() {
if ($this->problem == True)
print 'BUM !!!';
}
}
function test() {
$poCoToRobic = new SzukamGuza();
$poCoToRobic->problem =
True
;
$poCoToRobic->bum();
}
12
Wynik działania skryptu
BUM !!!
13
$this
■
Dostęp do składowych z metod klasy odbywa się
za pomocą specjalnej zmiennej $this, która
odnosi się do aktualnego obiektu.
class Zarowka {
private $zapalona;
public function zapal() {
$this
->zapalona = True;
}
public function zgas() {
$this
->zapalona = False;
}
}
14
Dostęp do definicji klasy
■
Aby móc używać klasy, która jest zdefiniowana
w innym pliku, należy plik, w którym jest
zdefiniowana klasa, załadować za pomocą
require_once
require_once 'nazwa_pliku.php';
15
Powtórzenie
■
Pole jest to zmienna wewnątrz obiektu.
■
Metoda jest to funkcja wewnątrz klasy.
■
Wszystkie pola klasy muszą być zadeklarowane
i poprzedzone jednym ze słów kluczowych
określających ich widoczność: public,
protected lub private.
■
W przypadku definiowania metod, określenie ich
widoczności jest opcjonalne, lecz polecane.
Domyślnie metody są publiczne.
■
Aby klasa była widoczna wewnątrz pliku, który
z niej korzysta, należy załadować plik, w którym
jest zdefiniowana z wykorzystaniem
require_once
16
Powtórzenie
■
Do tworzenia obiektów klasy służy słowo kluczowe
new
■
Zmienna $this wewnątrz klasy odnosi się do
aktualnego obiektu
■
Dostęp do składowych (pól i metod) klasy
zapewnia operator ->
■
Uzyskując dostęp do pola klasy za pomocą
operatora -> opuszczamy znak $ przed nazwą
pola
■
Próba dostępu do składowej chronionej lub
prywatnej spoza klasy spowoduje błąd
■
Dostęp do pól prywatnych możemy zapewnić za
pomocą publicznych metod klasy
17
Konstruktor
■
W PHP5 nazwa konstruktora __construct()
rozpoczyna się od dwóch znaków podkreślenia „_”
class Zarowka {
private $zapalona;
public function
__construct
($stan) {
$this->zapalona = $stan;
}
}
Konstruktorem
nazywamy
specjalną
metodę
automatycznie wywoływaną w trakcie tworzenia obiektu,
pozwalającą na nadanie początkowych wartości danym
obiektu.
Konstruktorem
nazywamy
specjalną
metodę
automatycznie wywoływaną w trakcie tworzenia obiektu,
pozwalającą na nadanie początkowych wartości danym
obiektu.
18
Destruktor
■
W PHP5 nazwa destruktora __destruct()
rozpoczyna się od dwóch znaków podkreślenia „_”
class Zarowka {
private $zapalona;
public function
__destruct
() {
print 'I po żarówce ...';
}
}
Destruktorem
nazywamy
specjalną
metodę
bezparametrową, która jest wywoływana zawsze
w momencie usuwania obiektu
Destruktorem
nazywamy
specjalną
metodę
bezparametrową, która jest wywoływana zawsze
w momencie usuwania obiektu
19
Przykład 1
class Zarowka {
private $zapalona;
public function __construct() {
print 'Oto zgaszona żarówka !!!<br />';
$this->zapalona = False;
}
public function __destruct() {
print 'I po żarówce ...<br />';
}
public function zapal() {
print 'Zapalam żarówkę...<br />';
$this->zapalona = True;
}
public function zgas() {
print 'Gaszę żarówkę...<br />';
$this->zapalona = False;
}
20
Przykład 1 cd.
public function stan() {
return $this->zapalona;
}
}
function opis($zr) {
print 'Żarówka jest ';
if ($zr->stan()) print 'zapalona.<br />';
else print 'zgaszona.<br />';
}
function test() {
$zr = new Zarowka();
$zr->zapal();
opis($zr);
$zr->zgas();
}
21
Wynik działania skryptu
Oto zgaszona żarówka !!!
Zapalam żarówkę...
Żarówka jest zapalona.
Gaszę żarówkę...
I po żarówce ...
22
Typy argumentów funkcji
■
Co się stanie, jeśli w poprzednim przykładzie
zapomnimy o znaku „$” i napiszemy:
function test() {
$zr = new Zarowka();
$zr->zapal();
opis(
zr
);
$zr->zgas();
}
■
Otrzymamy mniej więcej następujące błędy:
Notice:
Use of undefined constant zr - assumed 'zr'
in C:\wamp\www\skrypty\zarowka.php on line 33
Fatal error:
Call to a member function stan() on a
non-object
in C:\wamp\www\skrypty\zarowka.php on
line 25
23
Typy argumentów funkcji
■
Można tę sytuację zmienić określając
typ argumentu przyjmowanego przez funkcję
opis()
function opis(
Zarowka
$zr) {
if ($zr->stan()) print "zapalona.";
else print "zgaszona.";
}
■
Otrzymamy wtedy następujący błąd:
Catchable fatal error:
Argument 1 passed to opis()
must be an instance of Zarowka, string given
, called
in C:\wamp\www\skrypty\zarowka.php on line 33 and
defined in C:\wamp\www\skrypty\zarowka.php on line
25
24
Typy argumentów funkcji
■
Na pierwszy rzut oka wydaje się, że sytuacja
uległa pogorszeniu, jednak zyskujemy to, że:
Błąd zostaje wykryty wcześniej – w momencie
przekazania obiektu do funkcji, a nie w momencie jego
użycia
Błąd jest typu „
Catchable fatal error
”, co
przy wykorzystaniu mechanizmu wyjątków umożliwia
nam utrzymanie kontroli nad przebiegiem wykonania
programu
25
Przykład 2
class Lampa {
protected
$zarowka;
public function __construct (Zarowka $zarowka) {
print 'Wkręcam żarówkę<br />';
$this->zarowka = $zarowka;
}
public function zapal() {
$this->zarowka->zapal();
print 'Lampa zapalona<br />';
}
public function zgas() {
$this->zarowka->zgas();
print 'Lampa zgaszona<br />';
}
}
26
Dziedziczenie
■
Dziedziczenie pozwala na powtórne
wykorzystanie istniejącego kodu, ponieważ klasa
pochodna dziedziczy po klasie bazowej pola
i metody.
class pochodna
extends
bazowa {
// ciało klasy pochodnej
}
Dziedziczenie jest operacją polegającą na stworzeniu
nowej klasy (pochodnej) na bazie klasy już istniejącej
(bazowej).
Dziedziczenie jest operacją polegającą na stworzeniu
nowej klasy (pochodnej) na bazie klasy już istniejącej
(bazowej).
27
Przykład 3
class LampkaNocna
extends
Lampa {
private $sciemniacz;
public function __construct (Zarowka $zarowka) {
parent::__construct($zarowka);
$this->sciemniacz= new Sciemniacz($this->zarowka);
}
public function rozjasnij() {
$this->sciemniacz->rozjasnij();
}
public function sciemnij() {
$this->sciemniacz->sciemnij();
}
}
■
Zapis
parent::
__construct($zarowka);
oznacza wywołanie konstruktora klasy bazowej (Lampa)
i przekazanie mu wartości zmiennej $zarowka.
28
Przykład 3 cd.
class Sciemniacz {
private $zarowka;
private $poziomJasnosci = 100;
public function __construct (Zarowka $zarowka) {
$this->zarowka = $zarowka;
}
public function rozjasnij() {
if ($this->poziomJasnosci < 100) {
$this->poziomJasnosci++;
print 'Rozjaśniam światło żarówki<br>';
}
}
public function sciemnij() {
if ($this->poziomJasnosci > 1) {
$this->poziomJasnosci--;
print 'Przyciemniam światło żarówki<br>';
}
}
}
29
Przykład 3 cd.
$zarowka = new Zarowka();
$lampka = new LampkaNocna($zarowka);
$lampka->zapal();
$lampka->rozjasnij();
$lampka->sciemnij();
$lampka->sciemnij();
$lampka->rozjasnij();
$lampka->rozjasnij();
$lampka->rozjasnij();
$lampka->zgas();
30
Wynik działania skryptu
Oto zgaszona żarówka !!!
Wkręcam żarówkę
Zapalam żarówkę...
Lampa zapalona
Przyciemniam światło żarówki
Przyciemniam światło żarówki
Rozjaśniam światło żarówki
Rozjaśniam światło żarówki
Gaszę żarówkę...
Lampa zgaszona
I po żarówce ...
31
Przykład 4
class LampaOgrodowa
extends
Lampa {
private $czujnikRuchu;
public function __construct (Zarowka $zarowka)
{
parent::_construct($zarowka);
$this->czujnikRuchu = new
CzujnikRuchu($this->zarowka);
$this->czujnikRuchu->uruchom();
}
}
32
Przykład 4 cd.
class CzujnikRuchu {
private $zarowka;
public __construct(Zarowka $zarowka) {
$this->zarowka = $zarowka;
}
public function uruchom() {
print 'Czujnik ruchu uruchomiony<br>';
//wykrywanie ruchu...
}
private function wykrytoRuch() {
print 'Wykryto ruch<br>';
$this->zarowka->wlacz();
}
private function ruchZanikl() {
print 'Ruch zanikl<br>';
$this->zarowka->wylacz();
}
}
33
Przykład 5
function test(Lampa $lampa) {
$lampa->zapal();
$lampa->zgas();
}
$zarowka = new Zarowka();
$lampkaNocna = new LampkaNocna ($zarowka);
test($lampkaNocna);
print '<br>';
$lampaOgrodowa = new LampaOgrodowa
($zarowka);
test($lampaOgrodowa);
34
Wynik działania skryptu
Oto zgaszona żarówka !!!
Wkręcam żarówkę
Zapalam żarówkę...
Lampa zapalona
Gaszę żarówkę...
Lampa zgaszona
Wkręcam żarówkę
Czujnik ruchu uruchomiony
Zapalam żarówkę...
Lampa zapalona
Gaszę żarówkę...
Lampa zgaszona
I po żarówce ...
35
Wiele klas pochodnych
■
Klasa pochodna może mieć tylko jedną klasę
bazową, ale może być klasą bazową dla wielu
klas pochodnych
class Samochod {
// ...
}
class SamochodCiezarowy
extrends
Samochod {
// ...
}
class SamochodOsobowy
extrends
Samochod {
// ...
}
36
Nadpisywanie
■
Pola i metody dziedziczone z klasy bazowej mogą
być nadpisywane w klasie pochodnej
class Zarowka {
private $zapalona;
public function __construct() {
print "Oto zgaszona żarówka !!!";
$this->zapalona = False;
}
public function __destruct() {
print "I po żarówce ...";
}
public function zapal() {
print "Zapalam żarówkę...";
$this->zapalona = True;
}
// ...
}
37
Nadpisywanie
class ZarowkaEnergooszczedna extends Zarowka {
public function __construct() {
parent::__construct();
print "Energooszczędna !!!";
}
public function __destruct() {
parent::__destruct();
print "Utylizacja ...";
}
public function zapal() {
parent::zapal();
print "Taniej !!!";
}
// ...
}
38
Składowe statyczne
■
Do deklarowania składowych statycznych służy
słowo kluczowe static:
class Zarowka {
// ...
private
static
$licznikZarowek = 0;
public
static
function ileZarowek() {
return $licznikZarowek;
}
//...
}
Składowe (pola i metody) statyczne są to składowe
klasy, które nalezą się do całej klasy, a nie, tak jak
zwykłe składowe, do pojedynczej instancji (obiektu)
klasy.
Składowe (pola i metody) statyczne są to składowe
klasy, które nalezą się do całej klasy, a nie, tak jak
zwykłe składowe, do pojedynczej instancji (obiektu)
klasy.
39
Składowe statyczne
■
Ponieważ składowe statyczne należą do całej
klasy, a nie do konkretnego obiektu, można ich
używać nawet wtedy, kiedy nie istnieje żaden
obiekt danej klasy.
■
Dostęp do składowych statycznych zapewnia
operator zasięgu „::”
print Zarowka
::
ileZarowek();
40
Przykład 6
class Zarowka {
private static $licznikZarowek = 0;
private $zapalona;
public function __construct() {
print 'Oto zgaszona żarówka !!!<br>';
$this->zapalona = False;
self::
$licznikZarowek++;
}
public function __destruct() {
print 'I po żarówce ...<br>';
self::
$licznikZarowek--;
}
public function zapal() {
print 'Zapalam żarówkę...<br>';
$this->zapalona = True;
}
public function zgas() {
print 'Gaszę żarówkę...<br>';
$this->zapalona = False;
}
41
Przykład 6 cd.
public function stan() {
return $this->zapalona;
}
public static function ileZarowek() {
return
self::
$licznikZarowek;
}
}
function test() {
// w tym momencie nie istnieje jeszcze żaden
// obiekt klasy Zarowka !!!
print Zarowka::ileZarowek().'<br>';
$zr = new Zarowka();
print Zarowka::ileZarowek().'<br>';
$zr->zapal();
$zr->zgas();
$zr2 = new Zarowka();
print Zarowka::ileZarowek().'<br>';
}
42
Wynik działania skryptu
0
Oto zgaszona żarówka !!!
1
Zapalam żarówkę...
Gaszę żarówkę...
Oto zgaszona żarówka !!!
2
I po żarówce ...
I po żarówce ...
43
Powtórzenie
■
Aby zdefiniować klasę pochodną, należy
wykorzystać słowo kluczowe extends podając
nazwę klasy bazowej.
■
Klasa pochodna może mieć tylko jedną klasę
bazową, ale może być klasą bazową dla wielu
klas pochodnych.
■
Klasa pochodna ma dostęp do wszystkich
składowych swojej klasy bazowej i jej klas
bazowych (jeśli istnieją), z wyjątkiem składowych,
które zostały zadeklarowane jako prywatne.
■
Pola i metody dziedziczone z klasy bazowej mogą
być nadpisywane w klasie pochodnej.
44
Powtórzenie
■
Dostęp do składowej klasy bazowej nadpisanej
w klasie pochodnej można uzyskać za pomocą
parent::
■
Aby zdefiniować składową w zasięgu klasy należy
użyć static
■
Dostęp do składowych statycznych można
uzyskać za pomocą parent::, self:: lub
nazwa_klasy::