Metode statice PHP. Proprietăți și metode statice în PHP Metode și proprietăți statice în PHP

Metode statice PHP. Proprietăți și metode statice în PHP Metode și proprietăți statice în PHP

Nu este un secret pentru nimeni că oamenilor le place să pună întrebări dificile în timpul interviurilor. Nu întotdeauna adecvat, nu întotdeauna legat de realitate, dar faptul rămâne un fapt - se întreabă. Desigur, întrebarea este diferită și, uneori, o întrebare care la prima vedere ți se pare stupidă are de fapt scopul de a testa cât de bine cunoști limba în care scrii.

Să încercăm să defalcăm una dintre aceste întrebări - ce înseamnă cuvântul „static” în PHP și de ce este folosit?

Cuvântul cheie static are trei semnificații diferite în PHP. Să le privim în ordine cronologică, așa cum au apărut în limbă.

Prima valoare este o funcție variabilă locală statică foo() ( $a = 0; echo $a; $a = $a + 1; ) foo(); // 0 foo(); // 0 foo(); // 0

În PHP, variabilele sunt locale. Aceasta înseamnă că o variabilă definită și dată o valoare într-o funcție (metodă) există doar în timpul execuției acelei funcție (metodă). Când metoda iese, variabila locală este distrusă, iar când reintră, este creată din nou. În codul de mai sus, o astfel de variabilă locală este variabila $a - există numai în interiorul funcției foo() și este creată din nou de fiecare dată când această funcție este apelată. Creșterea unei variabile în acest cod este lipsită de sens, deoarece chiar pe următoarea linie de cod funcția își va termina activitatea și valoarea variabilei se va pierde. Indiferent de câte ori numim funcția foo(), aceasta va scoate întotdeauna 0...

Totuși, totul se schimbă dacă punem cuvântul cheie static înainte de atribuire:

Funcția foo() ( static $a = 0; echo $a; $a = $a + 1; ) foo(); // 0 foo(); // 1 foo(); // 2

Cuvântul cheie static, scris înainte de a atribui o valoare unei variabile locale, are următoarele efecte:

  • Atribuirea se efectuează o singură dată, la primul apel la funcție
  • Valoarea unei variabile marcate în acest fel este salvată după terminarea funcției.
  • La apelurile ulterioare ale funcției, în loc de atribuire, variabila primește valoarea stocată anterior
  • Această utilizare a cuvântului static se numește o variabilă locală statică Capcanele variabilelor statice Desigur, ca întotdeauna în PHP, există câteva capcane.

    Prima piatră este că numai constante sau expresii constante pot fi atribuite unei variabile statice.
    Iată codul:
    static $a = bar();

    va duce inevitabil la o eroare de analiză. Din fericire, începând cu versiunea 5.6, a devenit posibilă alocarea nu numai de constante, ci și de expresii constante (de exemplu, „1+2” sau „”), adică expresii care nu depind de alt cod și pot fi calculate la etapa de compilare
    A doua piatră este că metodele există într-o singură copie.
    Aici totul este puțin mai complicat. Pentru a înțelege esența, iată codul:
    clasa A (funcția publică foo() ( static $x = 0; echo ++$x; ) ) $a1 = nou A; $a2 = A nou; $a1->foo(); // 1 $a2->foo(); // 2 $a1->foo(); // 3 $a2->foo(); // 4

    Spre deosebire de așteptările intuitive „diferite obiecte - metode diferite”, vedem clar în acest exemplu că metodele dinamice din PHP „nu se înmulțesc”. Chiar dacă avem o sută de obiecte din această clasă, metoda va exista doar într-o singură instanță, doar că un $this diferit va fi aruncat în ea cu fiecare apel.

    Acest comportament poate fi neașteptat pentru un dezvoltator care nu este pregătit pentru el și poate fi o sursă de erori. Trebuie remarcat faptul că moștenirea clasei (și a metodei) duce la crearea unei noi metode:

    Clasa A (funcția publică foo() ( static $x = 0; echo ++$x; ) ) clasa B extinde A ( ) $a1 = nou A; $b1 = nou B; $a1->foo(); // 1 $b1->foo(); // 1 $a1->foo(); // 2 $b1->foo(); // 2

    Concluzie: Metodele dinamice în PHP există în contextul claselor, nu al obiectelor. Și numai în timpul de execuție apare substituția „$this = current_object”.

    A doua semnificație este proprietățile statice și metodele claselor În modelul de obiecte PHP, este posibil să se stabilească proprietăți și metode nu numai pentru obiecte - instanțe ale unei clase, ci și pentru clasă în ansamblu. Cuvântul cheie static este folosit și pentru aceasta:
    Clasa A ( public static $x = "foo"; public static function test() ( return 42; ) ) echo A::$x; // "foo" echo A::test(); // 42

    Pentru a accesa astfel de proprietăți și metode, sunt folosite construcții cu două puncte („Paamayim Nekudotayim”), cum ar fi CLASS_NAME::$Variablename și CLASS_NAME::Methodname().

    Prima caracteristică este banală - nu există $this.

    De fapt, aceasta provine din însăși definiția unei metode statice - deoarece este asociată cu o clasă, nu cu un obiect, această pseudovariabilă $, care indică obiectul curent în metodele dinamice, nu este disponibilă. Ceea ce este complet logic.

    Cu toate acestea, trebuie să știți că, spre deosebire de alte limbi, PHP nu detectează situația „$this is written in a static method” la etapa de analiză sau compilare. O eroare ca aceasta poate apărea numai în timpul rulării dacă încercați să executați cod cu $this într-o metodă statică.
    Cod astfel:
    clasa A ( public $id = 42; funcția publică statică foo() ( echo $this->id; ) )
    nu va provoca erori, atâta timp cât nu încercați să utilizați metoda foo() în mod necorespunzător:

    $a = A nou; $a->foo();
    (și imediat obțineți „Eroare fatală: Folosind $this când nu este în contextul obiectului”)
    A doua caracteristică este că static nu este o axiomă!

    clasa A (funcție publică statică foo() ( echo 42; ) ) $a = nou A; $a->foo();
    Asta e, da. O metodă statică, dacă nu conține $this în cod, poate fi apelată într-un context dinamic, ca o metodă obiect. Aceasta nu este o eroare în PHP.
    Reversul nu este în întregime adevărat:

    clasa A (funcția publică foo() ( echo 42; ) ) A::foo();

    O metodă dinamică care nu utilizează $this poate fi executată într-un context static. Cu toate acestea, veți primi un avertisment „Metoda non-statică A::foo() nu trebuie apelată static” la nivelul E_STRICT. Depinde de dvs. să decideți dacă respectați cu strictețe standardele de cod sau suprimați avertismentele. Prima, desigur, este de preferat.

    Și apropo, tot ce este scris mai sus se aplică doar metodelor. Utilizarea unei proprietăți statice prin „->” este imposibilă și duce la o eroare fatală.

    A treia semnificație, care pare a fi cea mai complexă - legarea statică târzie Dezvoltatorii limbajului PHP nu s-au oprit la două semnificații ale cuvântului cheie „static”, iar în versiunea 5.3 au adăugat o altă „funcție” a limbajului, care este implementată. cu acelasi cuvant! Se numește „legare statică târzie” sau LSB (legare statică târzie).
    Cel mai simplu mod de a înțelege esența LSB este cu exemple simple:
    Această caracteristică de limbă se numește „legare statică timpurie”. De ce devreme? Deoarece legarea lui self și a unui nume de clasă specific nu are loc în timpul de execuție, ci în etapele anterioare - analizarea și compilarea codului. Ei bine, „static” - pentru că vorbim despre proprietăți și metode statice.

    Să ne schimbăm puțin codul:

    Model de clasă ( public static $table = „tabel”; funcția publică statică getTable() ( return self::$table; ) ) class User extinde Model (public static $table = „utilizatori”; ) echo User::getTable() ; // "masa"

    Acum înțelegeți de ce PHP se comportă neintuitiv în această situație. self a fost asociat cu clasa Model atunci când nu se știa nimic despre clasa User și, prin urmare, indică Model.

    Ce ar trebuii să fac?

    Pentru a rezolva această dilemă, în etapa de execuție a fost inventat un mecanism de legare „târzie”. Funcționează foarte simplu - scrieți doar „static” în loc de cuvântul „self” și conexiunea se va stabili cu clasa care apelează acest cod, și nu cu cea în care este scris:
    clasă Model ( public static $table = "tabel"; public static function getTable() ( return static::$table; ) ) class User extinde Model (public static $table = "utilizatori"; ) echo User::getTable() ; // "utilizatori"

    Aceasta este misterioasa „legare statică târzie”.

    Trebuie remarcat faptul că, pentru o mai mare comoditate, în PHP, pe lângă cuvântul „static”, există și o funcție specială get_called_class(), care vă va spune în contextul cărei clase funcționează codul dvs.

    Interviuri fericite!

    PHP are capacitatea de a defini o metodă ca fiind statică. O metodă statică nu are acces la proprietățile unui obiect. Astfel de metode pot fi apelate numai în contextul unei clase, nu în contextul unui obiect.

    Cel mai important lucru de înțeles este că proprietățile și metodele statice aparțin claselor, nu obiectelor.

    Un exemplu va clarifica imediat. Să creăm un obiect Math (prescurtare de la matematică în engleză).

    Metode statice PHP

    Această clasă oferă instrumente pentru lucrul cu funcții matematice fără a fi nevoie să creați un obiect. Clasa are un constructor care incrementează proprietatea statică $count cu unu. Clasa își amintește valoarea acestei proprietăți deoarece este statică.

    Apropo, pentru a declara o metodă sau o proprietate statică, utilizați cuvântul static și pentru a accesa o proprietate statică, utilizați cuvântul self urmat de două puncte duble „ ::”.

    Toate acestea se înțeleg mai bine prin comparație, mai ales comparând un exemplu de lucru cu unul eronat. Să extindem puțin exemplul nostru.

    Metode statice PHP

    În acest exemplu, am adăugat o proprietate obișnuită $counter la clasă, care a fost, de asemenea, incrementată cu unu în constructor. Dar o proprietate obișnuită aparține unui obiect, deci nu persistă între apelurile obiectului. Ori de câte ori este creată o instanță a unei clase (obiect), proprietatea va fi egală cu zero în constructor va fi mărită cu unu;

    O proprietate statică aparține clasei, deci valoarea acesteia este păstrată.

    Mai jos sunt câteva exemple care arată cum funcționează proprietățile și metodele statice.

    Încercarea de a utiliza variabila $this într-o metodă statică va avea ca rezultat o eroare (Eroare fatală: Utilizarea $this atunci când nu este în contextul obiectului).

    Metode statice PHP

    În acest exemplu, dacă eliminați cuvântul static înainte de numele proprietății, va apărea eroarea „Acces la proprietate statică nedeclarată”.

    Nu există proprietăți statice pe obiectele de clasă.

    Metode statice PHP

    O metodă statică poate fi apelată folosind constructul self::method(). Exemplu:

    Metode statice PHP

    O proprietate statică poate fi obținută în contextul unei clase folosind sintaxa:

    echo TestClass::$age;

    Mai mult, o încercare de a accesa o proprietate obișnuită în acest fel va duce la eroarea: „Eroare fatală: Acces la proprietate statică nedeclarată”.

    O proprietate statică poate fi modificată în contextul unei clase folosind sintaxa:

    TestClass::$age += 20; // De exemplu

    Un alt exemplu de cod cu metode și proprietăți statice

    Acest exemplu arată, de asemenea, opțiuni simple pentru utilizarea metodelor și proprietăților statice. Cu cât înțelegeți mai simplu codul, cu atât vă veți aminti mai bine materialul.

    Metode statice PHP

    Vă rugăm să rețineți, și acest lucru este important, în acest exemplu am accesat metoda non-static sayHi() folosind sintaxa pentru accesarea membrilor clasei statice.

    Relua
    • Principalul lucru: proprietățile statice aparțin claselor, nu obiectelor.
    • Dintr-o metodă statică nu puteți accesa proprietățile și metodele obișnuite ale clasei $this->name nu funcționează aici.
    • Dintr-o metodă statică, puteți accesa proprietățile statice folosind self::$name .
    • Proprietățile statice ale unei clase nu sunt disponibile pentru obiecte.
    • O metodă normală poate accesa o proprietate statică folosind self::$name .
    • O proprietate statică poate fi obținută în contextul unei clase folosind sintaxa: TestClass::$age .
    • O metodă obișnuită poate fi apelată atât în ​​contextul unui obiect ($object->method()) cât și al unei clase folosind sintaxa TestClass::method().
    • Folosind sintaxa $object::$age, am putut accesa o proprietate statică printr-un obiect.
    Paralele cu JavaScript

    JavaScript are o clasă Math care conține multe funcții matematice diferite.

    Pentru a efectua calcule matematice (calcularea sinusului sau exponentului) în JavaScript, nu trebuie să creați un obiect din clasa Math, deoarece metodele sale sunt statice. Înainte de a învăța PHP, nu puteam să înțeleg ce este, și abia după ce am studiat clasele și obiectele în PHP mi-a căzut totul la loc în cap.

    De fapt, este foarte convenabil să ai acces direct la metodele matematice ale clasei Math fără a fi nevoie să creezi un obiect.

    O caracteristică foarte importantă a OOP este prezența proprietăților și metodelor statice. Principalul lucru este că trebuie să înțelegeți imediat că astfel de proprietăți și metode nu aparțin obiectului, ci clasei. Acest lucru trebuie înțeles de la bun început, dar mă voi uita la utilizarea proprietăților și metodelor statice în PHP în acest articol.

    Cel mai clasic exemplu este o clasă responsabilă pentru funcții matematice. Dacă cineva știe Java, atunci știe că există o clasă Math (JavaScript are și o astfel de clasă), care conține multe funcții matematice. Și metodele sunt statice. Aceasta înseamnă că pentru a calcula orice sinus sau exponent, nu trebuie să creați un obiect din această clasă, ceea ce este foarte convenabil.

    Să scriem o copie mai mică a acestei clase, dar numai pentru PHP:

    În acest cod am arătat utilizarea metodelor și proprietăților statice. Vă rugăm să rețineți că am implementat metoda clasică de contor de obiecte. Acest lucru sa întâmplat doar pentru că câmpul de numărare este static și are aceeași valoare pentru toate obiectele.

    Un alt exemplu popular de utilizare a metodelor și proprietăților statice este înregistrarea în jurnal. Toate intrările sunt adăugate prin metode statice. De asemenea, este foarte obișnuit să se creeze o clasă constând din mai multe setări și acolo, de asemenea, toate câmpurile sunt statice. După cum puteți vedea, există mai mult decât suficiente exemple de utilizare a metodelor și proprietăților statice în PHP și în alte limbi, așa că este imperativ să puteți lucra cu ele.

    Late Static Binding (LSB) a fost un subiect fierbinte de discuție în ultimii trei ani în cercurile de dezvoltare PHP (și în sfârșit l-am prins în PHP 5.3). Dar de ce este nevoie? În acest articol, vom examina exact cum legarea statică tardivă vă poate simplifica foarte mult codul.

    La o întâlnire a dezvoltatorilor PHP organizată la Paris în noiembrie 2005, subiectul legăturii statice târzii a fost discutat oficial de echipa de dezvoltare de bază. Au fost de acord să-l pună în aplicare, împreună cu multe alte subiecte care erau pe ordinea de zi. Detaliile urmau să fie convenite prin discuții deschise.

    Din moment ce legarea statică tardivă a fost anunțat ca o funcție viitoare, au trecut doi ani. Și în cele din urmă LSB a devenit disponibil pentru utilizare în PHP 5.3. Dar acest eveniment a trecut neobservat de dezvoltatorii care folosesc PHP, din note doar o pagină din manual.

    Pe scurt, noua funcționalitate de legare statică tardivă permite obiectelor să moștenească în continuare metode din clasele părinte, dar în plus permite metodelor moștenite să aibă acces la constantele statice, metodele și proprietățile clasei copil, nu doar clasa părinte. Să ne uităm la un exemplu:

    Class Beer ( const NUME = "Bere!"; funcția publică getName() ( return self::NAME; ) ) clasa Ale extinde Bere ( const NUME = "Ale!"; ) $bereBăutură = bere nouă; $aleDrink = Ale noua; ecou "Bere este: " . $beerDrink->getName() ."\n"; echo "Ale este: " . $aleDrink->getName() ."\n";

    Acest cod va produce următorul rezultat:

    Berea este: berea! Ale este: Bere!

    Clasa Ale moștenește metoda getName(), dar self indică în continuare clasa în care este folosită (în acest caz, clasa Beer). Aceasta a rămas în PHP 5.3, dar a fost adăugat cuvântul static. Să ne uităm din nou la exemplu:

    Class Beer ( const NAME = "Bere!"; funcția publică getName() ( return self::NAME; ) public function getStaticName() ( return static::NAME; ) ) clasa Ale extinde Beer ( const NAME = "Ale!" ; ) $beerDrink = bere noua; $aleDrink = Ale noua; ecou "Bere este: " . $beerDrink->getName() ."\n"; echo "Ale este: " . $aleDrink->getName() ."\n"; ecou "Bere este de fapt: " . $beerDrink->getStaticName() ."\n"; echo "Ale este de fapt: " . $aleDrink->getStaticName() ."\n";

    Noul cuvânt cheie static specifică faptul că trebuie utilizată constanta de clasă moștenită în locul constantei care a fost definită în clasa în care este declarată metoda getStaticName(). Cuvântul static a fost adăugat pentru a implementa o nouă funcționalitate și, pentru compatibilitate cu înapoi, self funcționează la fel ca în versiunile anterioare de PHP.

    Pe plan intern, principala diferență (și, de fapt, motivul pentru care legarea este numită întârziată) dintre aceste două metode de acces este că PHP va determina valoarea pentru self::NAME la momentul „compilării” (când caracterele PHP sunt convertite în cod de mașină). care va fi procesat motor Zend), iar pentru static::NAME valoarea va fi determinată la pornire (în momentul în care codul mașină este executat în motorul Zend).

    Acesta este un alt instrument pentru dezvoltatorii PHP. În a doua parte ne vom uita la modul în care poate fi folosit pentru totdeauna.

    Late Static Binding (LSB) a fost un subiect fierbinte de discuție în ultimii trei ani în cercurile de dezvoltare PHP (și în sfârșit l-am prins în PHP 5.3). Dar de ce este nevoie? În acest articol, vom examina exact cum legarea statică tardivă vă poate simplifica foarte mult codul.

    La o întâlnire a dezvoltatorilor PHP organizată la Paris în noiembrie 2005, subiectul legăturii statice târzii a fost discutat oficial de echipa de dezvoltare de bază. Au fost de acord să-l pună în aplicare, împreună cu multe alte subiecte care erau pe ordinea de zi. Detaliile urmau să fie convenite prin discuții deschise.

    Din moment ce legarea statică tardivă a fost anunțat ca o funcție viitoare, au trecut doi ani. Și în cele din urmă LSB a devenit disponibil pentru utilizare în PHP 5.3. Dar acest eveniment a trecut neobservat de dezvoltatorii care folosesc PHP, din note doar o pagină din manual.

    Pe scurt, noua funcționalitate de legare statică tardivă permite obiectelor să moștenească în continuare metode din clasele părinte, dar în plus permite metodelor moștenite să aibă acces la constantele statice, metodele și proprietățile clasei copil, nu doar clasa părinte. Să ne uităm la un exemplu:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    clasa bere (
    const NUME = "Bere!" ;

    return self :: NUME ;
    }
    }
    clasa Ale extinde bere (
    const NUME = "Ale!" ;
    }

    $beerDrink = bere noua;
    $aleDrink = Ale noua;

    ecou "Bere este: " .
    $beerDrink -> getName() . „\n” ;

    Acest cod va produce următorul rezultat:

    echo "Ale este: " .

    $aleDrink -> getName() . „\n” ;

    Clasa Ale moștenește metoda getName(), dar self indică în continuare clasa în care este folosită (în acest caz, clasa Beer). Aceasta a rămas în PHP 5.3, dar a fost adăugat cuvântul static. Să ne uităm din nou la exemplu:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23

    clasa bere (
    const NUME = "Bere!" ;
    Berea este: berea!
    return self :: NUME ;
    }
    Ale este: Bere!
    funcția publică getName() (
    }
    }

    clasa Ale extinde bere (
    const NUME = "Ale!" ;
    }

    $beerDrink = bere noua;

    $aleDrink = Ale noua;

    ecou "Bere este: " .
    $beerDrink -> getName() . „\n” ;

    funcția publică getStaticName() (
    returnează static::NUME ;

    Noul cuvânt cheie static specifică faptul că trebuie utilizată constanta de clasă moștenită în locul constantei care a fost definită în clasa în care este declarată metoda getStaticName(). Cuvântul static a fost adăugat pentru a implementa o nouă funcționalitate și, pentru compatibilitate cu înapoi, self funcționează la fel ca în versiunile anterioare de PHP.

    Pe plan intern, principala diferență (și, de fapt, motivul pentru care legarea este numită întârziată) dintre aceste două metode de acces este că PHP va determina valoarea pentru self::NAME la momentul „compilării” (când caracterele PHP sunt convertite în cod de mașină). care va fi procesat motor Zend), iar pentru static::NAME valoarea va fi determinată la pornire (în momentul în care codul mașină este executat în motorul Zend).

    Acesta este un alt instrument pentru dezvoltatorii PHP. În a doua parte ne vom uita la modul în care poate fi folosit pentru totdeauna.