## Late Static Bindings (Resolución estática en tiempo de ejecución)

PHP implementa una funcionalidad llamada late static binding, en español la resolución estática en tiempo de ejecución, que puede ser utilizada para referenciar la clase llamada en un contexto de herencia estática.

Más precisamente, las resoluciones estáticas en tiempo de ejecución funcionan registrando el nombre de la clase en la última "llamada no reenviada". En el caso de las llamadas de métodos estáticos, se trata de la clase explícitamente nombrada (generalmente, la que está a la izquierda del operador `::`) ; en el caso de métodos no estáticos, se trata de la clase del objeto. Una "llamada reenviada" es una llamada estática introducida por `self::`, `parent::`, `static::`, o, subiendo en la jerarquía de clases, forward_static_call(). La función get_called_class() puede ser utilizada para recuperar una cadena que contiene el nombre de la clase llamada, y `static::` introduce su ámbito.

Esta funcionalidad ha sido bautizada como "late static bindings", con un punto de vista interno. "Late binding", literalmente resolución tardía, proviene del hecho de que los elementos `static::` no serán resueltos utilizando la clase donde el método ha sido definido, sino que será calculada utilizando la información en tiempo de ejecución. También se denomina "static binding" ya que puede ser utilizado para (sin estar limitado a) los métodos estáticos.

### Limitaciones de `self::`

Las referencias estáticas a la clase actual, con `self::` o `__CLASS__`, son resueltas utilizando la clase a la que pertenecen las funciones, es decir, donde fueron definidas:

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 ejemplo anterior mostrará:

    A

### Uso de la resolución estática en tiempo de ejecución

La resolución estática en tiempo de ejecución intenta superar esta limitación introduciendo una palabra clave que hace referencia a la clase que ha sido llamada durante la ejecución. Para simplificar, esta palabra clave permite la referencia a `B` desde `test()`, en el ejemplo anterior. Se decidió no introducir una nueva palabra clave, sino más bien utilizar la palabra `static` que ya estaba reservada.

Ejemplo #2 Uso simple de `static::`

    <?php

    class A
    {
        public static function who()
        {
            echo __CLASS__;
        }

        public static function test()
        {
            static::who(); // Aquí, resolución estática en tiempo de ejecución
        }
    }

    class B extends A
    {
        public static function who()
        {
             echo __CLASS__;
        }
    }

    B::test();

    ?>

El ejemplo anterior mostrará:

    B

> Nota:

> En contextos no estáticos, la clase llamada será la del objeto. Como `$this->` intentará llamar a métodos privados desde el mismo ámbito, utilizar `static::` podría dar resultados diferentes. Tenga en cuenta también que `static::` solo puede hacer referencia a propiedades estáticas.

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

    <?php

    class A
    {
        private function foo()
        {
            echo "Success!\n";
        }

        public function test()
        {
            $this->foo();
            static::foo();
        }
    }

    class B extends A
    {
       /* foo() será copiada en B, por lo tanto su ámbito será siempre A
        * y la llamada se realizará sin problemas */
    }

    class C extends A
    {
        private function foo()
        {
            /* El método original es reemplazado; el ámbito es el de C */
        }
    }

    $b = new B();
    $b->test();

    $c = new C();
    try {
        $c->test();
    } catch (Error $e) {
        echo $e->getMessage();
    }

    ?>

El ejemplo anterior mostrará:

    Success!
    Success!
    Success!
    Call to private method C::foo() from scope A

> Nota:

> La resolución de estáticos en tiempo de ejecución se detendrá en una llamada estática completamente resuelta. Por otro lado, las llamadas estáticas utilizando una palabra clave como `parent::` o `self::` reenviarán la información de llamada.

> Ejemplo #4 Llamadas con o sin reenvío

>     <?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 ejemplo anterior mostrará:

>     A
>     C
>     C

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open