Zaostřeno na PHP (2)

24. 9. 2002
Doba čtení: 5 minut

Sdílet

Dnešním dílem pokračuje prohlídka nových vlastností připravované verze PHP. Bude řeč o klonování objektů, soukromých atributech a dalších vylepšeních.
Soukromé atributy

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:

bitcoin_skoleni

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.

Autor článku

Michal Burda vystudoval informatiku a aplikovanou matematiku a nyní pracuje na Ostravské univerzitě jako odborný asistent. Zajímá se o data mining, Javu a Linux.