Quali sono esattamente i binding statici in ritardo in PHP?Quali sono esattamente i binding statici in ritardo in PHP?
risposta
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.
È 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.
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();
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.
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
.
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.
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
+1 La tua descrizione è semplice e chiara di quella trovata in PHP Manuale. – Mouli
questa dovrebbe essere la risposta accettata. è più semplice e utile –
ho trovato questo articolo davvero utile e descrittivo, dai un'occhiata [link] (https://www.techflirt.com/tutorials/oop-in-php/late-static-binding.html) –