Pro lepší zapouzdření informací do tříd můžete nyní definovat některé atributy jako private, tj. soukromé. Přístup k takovým atributům třídy pak je možný jen z metod dané třídy – z vnějšku k nim přistupovat nelze. Definicí atributu jako private máte jistotu, že si žádnou vnitřní hodnotu, která by se nikdy neměla používat přímo, nikde omylem nepřepíšete.
<?php class Test { private $x = 'Ahoj'; function pozdrav() { echo $this->x . '<br>'; } } class Testik extends Test { function takyPozdrav() { echo $this->x . '<br>'; } } $a = new Test(); $a->pozdrav(); printf('Tady nic není: (%s)<br>', $a->x); $b = new Testik(); echo 'Tady taky nic nebude...'; $b->takyPozdrav(); ?>
Tato malá ukázka dá na výstup následující text:
Ahoj Tady nic není: () Tady taky nic nebude...
V souvislosti s private atributy bych chtěl upozornit na jednu věc. Nevím jistě, jestli se jedná o vlastnost PHP, nebo spíše o chybu (a jestli to tak bude fungovat i ve finální verzi), ale zdá se, že každý druh atributů má svůj názvový prostor, takže klidně můžete mít tři různé (veřejné, soukromé a statické) atributy stejného jména. Zvažte následující příklad a jeho výsledek:
<?php class Test { var $x = "ahoj "; static $x = "nazdar "; private $x = "čau "; function tisk() { echo $this->x; } } $a = new Test(); echo $a->x; echo Test::$x; $a->tisk(); ?>
Výstup:
ahoj nazdar čau
V prvním echu přistupujeme k veřejné (var) proměnné objektu, druhým echem ke statickému (static) atributu třídy a voláním metody
tisk() k soukromému (private) atributu.
Klonování
Už když jsem se v minulém dílu zmínil o tom, že přiřazovacím operátorem se nyní nově objekty nekopírují, objevily se v diskusi dotazy, jak se tedy bude v případě potřeby kopírování provádět. Někteří další čtenáři už na dané téma odpovídali, ale já přesto vše zopakuji ještě jednou:
Klonování se provádí voláním metody __clone() klonovaného objektu. Po zavolání této metody se jádro PHP podívá, zda má daný objekt metodu __clone() definovánu, nebo ne. V záporném případě se spustí standardní klonovací metoda, která vytvoří identickou kopii objektu. Definováním vlastní metody __clone() získá programátor nad procesem klonování plnou kontrolu.
V metodě __clone() máte k dispozici speciální proměnnou $clone, která ukazuje na původní (klonovaný) objekt. Přitom platí, že standardní proměnná $this odkazuje na nově vytvářený klon.
<? class Ovce { var $jmeno; function __construct($jmeno) { $this->jmeno = $jmeno; } function __clone() { $this->jmeno = 'Klon ' . $clone->jmeno; } function vystup() { echo 'Já jsem ' . $this->jmeno . '<br>'; } } $dolly = new Ovce('Dolly'); $dolly->vystup(); $klon = $dolly->__clone(); $klon->vystup(); ?>
Výstup:
Já jsem Dolly Já jsem Klon Dolly
Pokud definujete vlastní metodu __clone(), musíte ručně inicializovat všechny atributy objektu. Autoři PHP slibují, že implementují nějaký mechanismus (pravděpodobně funkci), který provede automatickou bitovou kopii objektu a na tvůrce skriptů pak zbyde jen přepsat podle potřeby ty atributy, u kterých kopírování bit po bitu není na místě.
Přímé odkazování na objekty vrácené z volání funkce
Dalším krůčkem dopředu (který ostatně už měl být udělaný dávno) je, že objekt vrácený jako výsledek volání funkce či metody může být ihned odkazován:
<? class Vyrobek1 { function vystup() { echo 'Vyrobek 1<br>'; } } class Vyrobek2 { function vystup() { echo 'Vyrobek 2<br>'; } } class Tovarna { function vytvorVyrobek($druh) { if ($druh == 1) return new Vyrobek1(); else return new Vyrobek2(); } } $tovarna = new Tovarna(); $tovarna->vytvorVyrobek(1)->vystup(); $tovarna->vytvorVyrobek(2)->vystup(); ?>
Výsledek:
Vyrobek 1 Vyrobek 2
Referenční parametry mohou mít defaultní hodnotu
Další novinkou v jazyku PHP je to, že argumenty funkcí, které přebírají odkaz na proměnnou, mohou mít nyní defaultní hodnotu. Příklad:
<? function funkce(&$promenna = NULL) { if ($promenna === NULL) echo 'Funkce volaná bez parametru.<br>'; else echo $promenna++ . '<br>'; } $a = 1; funkce($a); funkce($a); funkce(); ?>
Výstup:
1 2 Funkce volaná bez parametru.
Statické atributy mohou být inicializovány
Další drobností ve vylepšeních PHP je fakt, že statické atributy tříd mohou být nyní inicializovány přímo ve svých definicích:
<? class NejakaTrida { static $promenna = 1; } echo NejakaTrida::$promenna; ?>
Co bude výsledkem takového příkladu, nemusím snad ani zveřejňovat…
Backtrackingem za snazší ladění
Pro snazší ladění budete moci v nové verzi PHP použít funkci debug_backtrace(), která vrací pole s informacemi o vnoření do volání funkcí. Prvky pole jsou asociativními poli s následujícími hodnotami:
- ‚class‘ – jméno třídy, ke které metoda patří (nebo prázdný řetězec, pokud se jedná o funkci),
- ‚function‘ – jméno volané funkce (metody),
- ‚file‘ – název zdrojového souboru, ve kterém došlo k volání,
- ‚line‘ – číslo řádku, ze kterého byla funkce volána.
Díky funkci debug_backtrace() získáte konkrétní představu o tom, jak funkce navzájem volají jedna druhou, a přehled, které funkce jsou rozpracovány. Možný způsob použití ukazuje následující příklad (čísla řádků jsou zde jen pro vaši informaci):
1 <? 2 function backtrace() { 3 $backtrace = debug_backtrace(); 4 5 foreach ($backtrace as $krok) { 6 $class = isset($krok['class']) ? $krok['class'] . '::' : ''; 7 8 echo $class . $krok['function'] . '() v souboru ' 9 . $krok['file'] . ' na řádku ' . $krok['line'] . '<br>'; 10 } 11 } 12 13 function nejaka_funkce() { 14 backtrace(); 15 } 16 17 function dalsi_funkce() { 18 nejaka_funkce(); 19 } 20 21 dalsi_funkce(); 22 ?>
A zde je výsledek ukázky:
backtrace() v souboru /var/www/html/testPHP43.php na řádku 14 nejaka_funkce() v souboru /var/www/html/testPHP43.php na řádku 18 dalsi_funkce() v souboru /var/www/html/testPHP43.php na řádku 21
A to je vše, alespoň pro dnešek. Z novinek v PHP nám na příště zbyly názvové prostory, nová práce s konstantami a výjimky.