Hlavní navigace

Zaostřeno na PHP (po roce) 3

Michal Burda 9. 9. 2003

Dokončení prohlídky vlastností připravovaného jazyka PHP 5.

Statické metody

S metodami v PHP 4 byl tak trochu problém. Nerozlišovalo se volání metody objektu od statického volání. PHP 5 zavádí po vzoru ostatních objektově orientovaných jazyků klíčové slovo static. Jeho užitečnost je ale v mých očích prozatím docela sporná (možná se do finální verze ještě leccos změní).

Použití nebo vynechání slova static v záhlaví metody vás nijak neomezuje ve volání metody oběma způsoby. Asi jediná výhoda spočívá v tom, že vás interpret PHP při pokusu o použití pseudo-proměnné $this uvnitř statické metody upozorní chybovou hláškou.

Nechci spekulovat, ale jistě by se dalo zařídit, aby PHP varovalo programátora i při statickém volání nestatické metody nebo nestatickém volání statické metody…

Příklad:

<?php
class NejakaTrida {
  public static function statickaFunkce() {
    ...
  }
  ...
}

NejakaTrida::statickaFunkce(); // statické volání
?>

Metody __get(), __set() a __call()

Další výbornou vlastnost jazyka PHP přináší trojice vyhrazených metod tříd z nadpisu tohoto odstavce. Pomocí nich můžete definovat akce spouštěné automaticky při přístupu k atributům nebo metodám objektu.

Vy, kteří už nějaké zkušenosti s objektově orientovaným programováním máte, jistě znáte ono dilema, zda k nějaké hodnotě objektu přistupovat přímo, nebo ji zapouzdřit do dvojice metod typu setHodnota($hod­nota) a getHodnota().

Od verze 5 alespoň v PHP tento „problém“ řešit nemusíte. V každé třídě můžete definovat metody __get() a __set() určené k tomu, aby obsluhovaly přístup k neznámým atributům. Funguje to asi takhle. Napíšete-li v programu příkaz:

$objekt->x = 3.8;

a proměnná x v definici třídy objektu $objekt neexistuje, pokusí se místo toho PHP vykonat příkaz

$objekt->__set('x', 3.8);

Vtip je v tom, že záleží jen a jen na vás, jak metodu __set() implementujete.

K doplňkovému účelu slouží i metoda __get() – PHP ji volá pro vrácení hodnoty nedefinovaného atributu.

Příklad:

<?php
class UpovidanaTrida {
    public $n;
    private $x = array("a" => 1, "b" => 2, "c" => 3);

    function __get($nazev) {
        echo "Pokus o získání '$nazev'\n";

        if (isset($this->x[$nazev])) {
            $hodnota = $this->x[$nazev];
            echo "Vracím: $hodnota\n";
            return $hodnota;
        } else {
            echo "Nelze!\n";
        }
    }

    function __set($nazev, $hodnota) {
        echo "Pokus o nastavení '$nazev' na $hodnota\n";

        if (isset($this->x[$nazev])) {
            $this->x[$nazev] = $hodnota;
            echo "OK!\n";
        } else {
            echo "Nelze!\n";
        }
    }
}

$objekt = new UpovidanaTrida();

echo "n:\n";
$objekt->n = 1;

echo "\na:\n";
$objekt->a += $objekt->b;

echo "\nz:\n";
$objekt->z++;

echo "\n";
var_dump($objekt);
?>

Na výstupu by se mělo objevit:

n:

a:
Pokus o získání 'b'
Vracím: 2
Pokus o získání 'a'
Vracím: 1
Pokus o nastavení 'a' na 3
OK!

z:
Pokus o získání 'z'
Nelze!
Pokus o nastavení 'z' na 1
Nelze!

object(upovidanatrida)#1 (2) {
  ["n"]=>
  int(1)
  [""]=>
  array(3) {
    ["a"]=>

    int(3)
    ["b"]=>
    int(2)
    ["c"]=>
    int(3)
  }
}

Vidíme, že v případě atributu $n se metody __set() a__get() nevolají, protože jde o atribut, který byl ve třídě náležitě definován. Rovněž si můžeme všimnout, že atributy lze používat nadále tak, jak jsme zvyklí, a že i složité výrazy PHP dekóduje do správné posloupnosti volání __set() a __get().

Dlužím vám ještě ukázat, k čemu je metoda __call(). Půjdeme rovnou k příkladu:

<?php
class DalsiUpovidanaTrida {
    function __call($nazev, $parametry) {
        echo "Volám $nazev:\n";
        var_dump($parametry);
        return 1;
    }

    function jarmilo($x) {
      return $x + 1;
    }
}

$objekt = new DalsiUpovidanaTrida();

$a = $objekt->hynku(1, '2', 3.4, true);
var_dump($a);
echo "\n";

$a = $objekt->vileme(3, 2, 1, 'start');
var_dump($a);
echo "\n";

$a = $objekt->jarmilo(3.1);
var_dump($a);
?>

Výstup:

Volám hynku:
array(4) {
  [0]=>

  int(1)
  [1]=>
  string(1) "2"
  [2]=>
  float(3.4)
  [3]=>
  bool(true)
}
int(1)

Volám vileme:
array(4) {
  [0]=>
  int(3)
  [1]=>
  int(2)
  [2]=>

  int(1)
  [3]=>
  string(5) "start"
}
int(1)

float(4.1)

Jak jste si asi všimli, metoda __call() má něco do činění s nedefinovanými metodami. Volání $objekt->hynku() a$objekt->vileme() vedlo k vykonání metody __call(), protože PHP nemohlo v definici třídy DalsiUpovidanaTrida nalézt jejich implementaci. V případě volání metody jarmilo() už PHP do metody __call() nezabruslilo.

__autoload()

Mechanismus __autoload() je spíše už jen kosmetickou úpravou nové syntaxe jazyka; onou často vzpomínanou třešinkou na dortu nebo gramem ptačího trusu na hnojišti velkokapacitního kravína. Umožňuje vykonat určitý kód v okamžiku instanciace nedeklarované třídy. Jako jediný argument se funkci předává název třídy.

Typické využití ukazuje následující příklad:

<
function __autoload($jmenoTridy) {
  include_once('moje_knihovna_trid/' . $jmenoTridy . '.php');
}

V souvislosti s tímto „vylepšením“ si ale dovedu představit určitý problém: dá se předpokládat, že __autoload() budou používat zejména knihovny tříd. Co když ale programátor bude chtít použít knihovny dvě, přičemž každá z nich si ponese svůj __autoload()? Inu, uvidíme, jak se s tím poperou…

Tímto náš obnovený seriál o PHP verze 5 končí. PHP přináší mnoho změn. Pro někoho to asi přinese řadu problémů s kompatibilitou se stávajícím kódem, ale to je bohužel nutné zlo na cestě vývojem, které pro dlouholeté uživatele tohoto skriptovacího jazyka jistě není novinkou. Nicméně objekty ve čtyřkové verzi byly opravdu hrozné (narážím zejména na přiřazování hodnotou) a zasloužily předělat.

PS: Pokud se v budoucnosti v syntaxi jazyka objeví nějaká další vylepšení, určitě se o nich na Rootu dočtete.

Našli jste v článku chybu?

22. 10. 2003 20:52

Jirka Hradil (neregistrovaný)

Sice pro Javu, ale na popis to staci, IMHO:

http://www.hradil.cz/view.php?cisloclanku=2003062701
http://www.hradil.cz/view.php?cisloclanku=2003062702




18. 9. 2003 18:01

Jakub Podhorský (neregistrovaný)

zdravim vim ze to sem uz nepatri ale o tomhle serialu jsem se dozvedel ais pred 3ma dny a mam dotaz na interface

mohl by me nekdo presne a podrobne vysvetlit pouziti Interface vubec jsem nepochopil jeho vyuziti protoze si udelam interface kde mam stejne jenom metody ktere me nic nedelaji a jsou prazdne a tudiz jsou me na nic a stejne jejich obsah musim delat ve scriptu s PHP delam uz delsi dobu a s objektama si uz taky delsi dobu hraju ale bohuzel jenom na urovni PHP a tak me asi vyuziti inte…

Podnikatel.cz: Babiše přesvědčila 89letá podnikatelka?!

Babiše přesvědčila 89letá podnikatelka?!

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

120na80.cz: Stoná vaše dítě často? Upravte mu jídelníček

Stoná vaše dítě často? Upravte mu jídelníček

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

Vitalia.cz: Znáte „černý detox“? Ani to nezkoušejte

Znáte „černý detox“? Ani to nezkoušejte

Měšec.cz: Kdy vám stát dá na stěhování 50 000 Kč?

Kdy vám stát dá na stěhování 50 000 Kč?

120na80.cz: Jak oddálit Alzheimera?

Jak oddálit Alzheimera?

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Podnikatel.cz: Zavře krám u #EET Malá pokladna a Teeta?

Zavře krám u #EET Malá pokladna a Teeta?

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru