2009-12-16 13 views

risposta

67

Dal PHP 5.3.0, PHP implementa una funzione chiamata tardiva statica vincolante che può essere utilizzato per fare riferimento alla classe denominata nel contesto di eredità statica.

Il binding statico tardivo tenta di risolvere tale limite introducendo una parola chiave che fa riferimento alla classe inizialmente chiamata in fase di esecuzione. Si è deciso di non introdurre una nuova parola chiave, ma piuttosto usare static che era già prenotato.

Vediamo un esempio:

<?php 
    class Car 
    { 
     public static function run() 
     { 
      return static::getName(); 
     } 

     private static function getName() 
     { 
      return 'Car'; 
     } 
    } 

    class Toyota extends Car 
    { 
     public static function getName() 
     { 
      return 'Toyota'; 
     } 
    } 

    echo Car::run(); // Output: Car 
    echo Toyota::run(); // Output: Toyota 
?> 

late static bindings lavoro memorizzando la classe denominata in ultima "chiamata non-forwarding". In caso di chiamate al metodo statico, questa è la classe esplicitamente chiamata (di solito quella a sinistra dell'operatore ::); in caso di chiamate al metodo non statiche, è la classe dell'oggetto.

A "chiamata" è uno statico che viene introdotto da self::, parent::, static::, o, se salendo nella gerarchia delle classi, forward_static_call().

La funzione get_called_class() può essere utilizzata per recuperare una stringa con il nome della classe chiamata e static:: ne introduce l'ambito.

158

È assolutamente necessario leggere Late Static Bindings nel manuale PHP. Tuttavia, cercherò di darti un breve riassunto.

Fondamentalmente, si riduce al fatto che la parola chiave self non segue le regole di ereditarietà. self si risolve sempre nella classe in cui viene utilizzato. Ciò significa che se si crea un metodo in una classe genitore e lo si chiama da una classe figlia, self non farà riferimento al figlio come ci si potrebbe aspettare.

Il binding statico tardivo introduce un nuovo utilizzo per la parola chiave static, che risolve questo particolare problema. Quando si utilizza static, rappresenta la classe in cui viene utilizzata per la prima volta, ad es. si "lega" alla classe runtime.

Questi sono i due concetti base dietro di esso. Il modo in cui , parent e static funzionano quando static è in gioco può essere sottile, quindi piuttosto che entrare in maggiori dettagli, ti consiglio vivamente di studiare gli esempi di pagina manuale. Una volta comprese le basi di ciascuna parola chiave, gli esempi sono abbastanza necessari per vedere quale tipo di risultati otterrai.

+24

+1 La tua descrizione è semplice e chiara di quella trovata in PHP Manuale. – Mouli

+2

questa dovrebbe essere la risposta accettata. è più semplice e utile –

+0

ho trovato questo articolo davvero utile e descrittivo, dai un'occhiata [link] (https://www.techflirt.com/tutorials/oop-in-php/late-static-binding.html) –

4

Ad esempio:

abstract class Builder { 
    public static function build() { 
     return new static; 
    } 
} 

class Member extends Builder { 
    public function who_am_i() { 
     echo 'Member'; 
    } 
} 

Member::build()->who_am_i(); 
20

Non è un comportamento molto evidente:

Il seguente codice produce 'AlphaBeta'.

class alpha { 

    function classname(){ 
     return __CLASS__; 
    } 

    function selfname(){ 
     return self::classname(); 
    } 

    function staticname(){ 
     return static::classname(); 
    } 
} 

class beta extends alpha { 

    function classname(){ 
     return __CLASS__; 
    } 
} 

$beta = new beta(); 
echo $beta->selfname(); // Output: alpha 
echo $beta->staticname(); // Output: beta 

Tuttavia, se togliamo la dichiarazione della funzione nomeclasse dalla classe versione beta, si ottiene 'alphaalpha' come il risultato.

+1

Questo è interessante . Ho dovuto controllare me stesso – instead

+1

Molto bello. La stessa cosa è mostrata nel manuale PHP, ma questo è molto più chiaro. Per riferimento: http://php.net/manual/en/language.oop5.late-static-bindings.php (vedi ex 4) – musicin3d

9

Sto citando dal libro: "PHP Master scrive codice all'avanguardia".

Il binding statico tardivo era una funzionalità introdotta con php 5.3. Permette a di ereditare metodi statici da una classe genitore e di fare riferimento alla chiamata classe figlio.

Questo significa che puoi avere una classe astratta con metodi statici, e implementazioni concrete di riferimento della classe bambino utilizzando il metodo statico :: () la notazione invece del self :: metodo().

Sentitevi liberi di dare un'occhiata alla documentazione ufficiale di PHP così: http://php.net/manual/en/language.oop5.late-static-bindings.php

Esempio:

<?php 
class Animal { 
    public static function StaticCall() { 
     // Parent object invokes its own getAnimalName() 
     // Child object invokes its own getAnimalName() instead of parent's getAnimalName() 
     return static::getAnimalName(); 
    } 

    public static function SelfCall() { 
     return self::getWeight(); 
    } 

    private static function getAnimalName(){ 
     return 'Animal <br />'; 
    } 

    private static function getWeight(){ 
     return '10 kg <br />'; 
    } 
} 

class Bird extends Animal { 
    public static function getAnimalName(){ 
     return 'Bird <br />'; 
    } 

    private static function getWeight(){ 
     return '2 kg <br />'; 
    } 
} 

echo Animal::StaticCall(); // Animal  
echo Animal::SelfCall(); // 10 kg   
echo Bird::StaticCall(); // Bird invokes method from own object 
echo Bird::SelfCall();  // 10 kg invokes method from parent 

Nel codice sopra potete vedere due classi Animal che è la classe padre e Bird che è la classe figlio. Entrambi Animal e Bird hanno un metodo getAnimalName() e getWeight(). La superclasse Animal ha due metodi: StaticCall() e SelfCall().

Il metodo StaticCall() invoca getAnimalName() utilizzando la parola chiave static.
Il metodo SelfCall() invoca getWeight() utilizzando la parola chiave self .

La domanda che ora abbiamo è: in quale contesto è eseguito getAnimalName()?

La risposta: static::getAnimalName() identifica il contesto e invoca il metodo in tale contesto.

Se si richiama Bird::StaticCall() il codice verrà eseguito StaticCall() che è in Animal. Quindi static::getAnimalName() invocherà ed eseguirà da Bird il metodo getAnimalName().

Ciò differisce dal self::, perché self:: richiama sempre il metodo nell'oggetto self è definita. Quindi, se self::getWeight() è definito in oggetto Animal nel metodo SelfCall() e Bird::SelfCall() sarebbe chiamato poi self::getWeight() invoca getWeight() nell'ambito dell'oggetto Animal .

4

Guardandolo da un "perché dovrei usare questo?" prospettiva, è fondamentalmente un modo per cambiare il contesto da cui viene interpretato/eseguito il metodo statico.

Con self, il contesto è quello in cui è stato definito originariamente il metodo. Con static, è quello da cui lo stai chiamando.

7

L'esempio più semplice per mostrare la differenza.
nota, self :: $ c

class A 
{ 
    static $c = 7; 

    public static function getVal() 
    { 
     return self::$c; 
    } 
} 

class B extends A 
{ 
    static $c = 8; 
} 

B::getVal(); // 7 

tardo binding statico, nota statica :: $ c

class A 
{ 
    static $c = 7; 

    public static function getVal() 
    { 
     return static::$c; 
    } 
} 

class B extends A 
{ 
    static $c = 8; 
} 

B::getVal(); // 8 
Problemi correlati