## Enlaces estáticos en tiempo de ejecución

Desde su versión 5.3.0, PHP incorpora una nueva funcionalidad llamada enlace estático en tiempo de ejecución ("late static bindings" en inglés) que permite referirse referencias a la clase invocada en un contexto de herencia estática.

De forma más precisa, un enlace estático en tiempo de ejecución funciona almacenando el nombre de clase de la última llamada que no tenga «propagación». En el caso de llamadas a métodos estáticos, se trata de la clase nombrada explícitamente (normalmente la que precede al operador `::`); en los casos de llamadas a métodos no estáticos, es clase del objeto. Una «llamada con propagación» es una llamada estática que precedida por `self::`, `parent::`, `static::`, o, siguiendo la jerarquía de clases, forward_static_call(). La función get_called_class() puede utilizarse para obtener una cadena con el nombre de la clase invocada, y `static::` revela cuál es su alcance.

A esta funcionalidad se le ha llamado «enlace estático en tiempo de ejecución» teniendo en cuenta un punto de vista interno. «Enlace en tiempo de ejecución» viene del hecho de que `static::` no será resuelto usando la clase donde el método está definido, sino que en su lugar se calculará utilizando información en tiempo de ejecución. También se le llamó «enlace estático» debido a que se puede utilizar (entre otras cosas) para llamadas a métodos estáticos.

### Limitaciones de `self::`

Las referencias estáticas a la clase en uso, como `self::` o `__CLASS__`, se resuelven empleando la clase a la que pertenece la función:

Ejemplo #1 Uso de `self::`

`<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>`

El resultado del ejemplo sería:

    A

### Uso de enlaces estático en tiempo de ejecución

Los enlaces estáticos en tiempo de ejecución tratan de resolver esta limitación empleando una palabra reservada que se refiera a la clase invocada inicialmente en tiempo de ejecución; básicamente, una palabra reservada que permita referirse a a `B` desde `test()`, según el ejemplo anterior. Se decidió no crear una nueva palabra reservada, si no utilizar en su lugar `static`, que ya era reservada.

Ejemplo #2 Uso básico de `static::`

`<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // He aquí el enlace estático en tiempo de ejecución
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>`

El resultado del ejemplo sería:

    B

> Nota:

> En contextos no estáticos, la clase invocada será la clase de la instancia del objeto. Dado que `$this->` trata de invocar métodos privados desde su mismo ámbito, el uso de `static::` puede dar diferentes resultados. Otra diferencia es que `static::` sólo puede referirse a propiedades estáticas.

Ejemplo #3 Uso de `static::` en un contexto no estático

`<?php
class A {
private function foo() {
echo "¡Éxito!\n";
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
/* foo() se copiará en B, por lo tanto su ámbito seguirá siendo A
* y la llamada tendrá éxito */
}
class C extends A {
private function foo() {
/* se reemplaza el método original; el ámbito del nuevo es ahora C */
}
}
$b = new B();
$b->test();
$c = new C();
$c->test(); //falla
?>`

El resultado del ejemplo sería:

    ¡Éxito!
    ¡Éxito!
    ¡Éxito!

    Fatal error:  Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

> Nota:

> En una llamada que se resuelva como estática, la resolución de enlaces estáticos en tiempo de ejecución se detendrá sin propagarse. Por otra parte, las llamadas estáticas que utilicen palabras reservadas como `parent::` o `self::` sí propagarán la información de llamada.

> Ejemplo #4 Llamadas que propagan y que no propagan la información de llamada

> `<?php
> class A {
> public static function foo() {
> static::who();
> }
> public static function who() {
> echo __CLASS__."\n";
> }
> }
> class B extends A {
> public static function test() {
> A::foo();
> parent::foo();
> self::foo();
> }
> public static function who() {
> echo __CLASS__."\n";
> }
> }
> class C extends B {
> public static function who() {
> echo __CLASS__."\n";
> }
> }
> C::test();
> ?>`

> El resultado del ejemplo sería:

>     A
>     C
>     C