Pregunta

¿Cuáles son exactamente fijaciones estáticas finales en PHP?

¿Fue útil?

Solución

Es imprescindible disponer de leer Late enlaces estáticos en el manual de PHP. Sin embargo, voy a tratar de darle un breve resumen.

Básicamente, todo se reduce al hecho de que la palabra clave self no sigue las mismas reglas de la herencia. self siempre se resuelve a la clase en la que se utiliza. Esto significa que si haces un método en una clase padre y lo llama de una clase hija, self no hará referencia al niño como se podría esperar.

Late enlace estático introduce un nuevo uso de la palabra clave static, que aborda esta deficiencia en particular. Cuando se utiliza static, que representa a la clase donde se utiliza por primera vez, es decir. Es une 'a la clase de tiempo de ejecución.

Estos son los dos conceptos básicos detrás de él. La forma self, parent y static funcionan cuando static está en juego puede ser sutil, por lo que en lugar de ir a más detalle, te recomiendo encarecidamente que estudie los ejemplos de páginas del manual. Una vez que entienda los conceptos básicos de cada palabra clave, los ejemplos son bastante que ver qué tipo de resultados que va a obtener.

Otros consejos

A partir de PHP 5.3.0, PHP implementa una función llamada tarde estática de unión que puede ser utilizado para hacer referencia a la clase llamada en el contexto de la herencia estática.

tardíos intentos de enlace estática para resolver esta limitación mediante la introducción de una palabra clave que hace referencia a la clase que se llamó inicialmente en tiempo de ejecución. Se decidió no introducir una nueva palabra clave, sino más bien utilizar static que ya estaba reservado.

Veamos un ejemplo:

<?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 trabajo mediante el almacenamiento de la clase mencionada en la última "llamada no reenvío". En el caso de las llamadas a métodos estáticos, esta es la clase llamada explícita (por lo general el de la izquierda de la :: operador); en caso de llamadas a métodos no estáticos, es la clase del objeto.

A "Desvío de llamadas" es una estática que se introduce por self::, parent::, static::, o, si se va para arriba en la jerarquía de clases, forward_static_call().

El get_called_class() función se puede utilizar para recuperar una cadena con el nombre de la clase llamada y static:: presenta su ámbito de aplicación.

No es un comportamiento muy evidente:

El código siguiente 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

Sin embargo, si eliminamos la declaración de la función nombre de clase de la clase beta, obtenemos 'alphaalpha' como el resultado.

cito del libro: "Maestro PHP escribir código de vanguardia".

  

Late estática de unión era una característica introducida con php 5.3. Permite   nosotros heredamos los métodos estáticos de una clase padre, y para referenciar   la clase de niño que se llama.

     

Esto significa que puede tener una clase abstracta con métodos estáticos, y   hacer referencia a implementaciones concretas de la clase infantil mediante el uso de la    estática :: método () notación en lugar de la auto :: método ().

No dude en echar un vistazo a la documentación oficial de PHP, así: http://php.net/manual/en/language. oop5.late-static-bindings.php


La forma más clara de explicar la ligadura estática es con un ejemplo sencillo. Echar un vistazo a las dos definiciones de las clases inferiores, y sigue leyendo.

class Vehicle {
    public static function invokeDriveByStatic() {
        return static::drive(); // Late Static Binding
    }
    public static function invokeStopBySelf() {
        return self::stop(); // NOT Late Static Binding
    }
    private static function drive(){
        return "I'm driving a vehicle";
    }
    private static function stop(){
        return "I'm stopping a vehicle";
    }
}

class Car extends Vehicle  {
    protected static function drive(){
        return "I'm driving a CAR";
    }
    private static function stop(){
        return "I'm stopping a CAR";
    }
}

Vemos una clase padre (vehículo) y una clase hija (Car). La clase principal tiene 2 métodos públicos:

  • invokeDriveByStatic
  • invokeStopBySelf

La clase dominante tiene 2 métodos privados:

  • drive
  • stop

La clase hija anula 2 métodos:

  • drive
  • stop

Ahora vamos a invocar a los métodos públicos:

  • invokeDriveByStatic
  • invokeStopBySelf

Pregúntese: ¿Qué clase invoca invokeDriveByStatic / invokeStopBySelf? La clase padre o hijo?

Tome un vistazo a continuación:

// This is NOT Late Static Binding
// Parent class invokes from Parent. In this case Vehicle.
echo Vehicle::invokeDriveByStatic(); // I'm driving a vehicle
echo Vehicle::invokeStopBySelf(); // I'm stopping a vehicle

// This is Late Static Binding.
// Child class invokes an inherited method from Parent.
// Child class = Car, Inherited method = invokeDriveByStatic().
// ...
// The inherited method invokes a method that is overridden by the Child class.
// Overridden method = drive()
echo Car::invokeDriveByStatic(); // I'm driving a CAR

// This is NOT Late Static Binding
// Child class invokes an inherited method from Parent.
// The inherited method invokes a method inside the Vehicle context.
echo Car::invokeStopBySelf(); // I'm stopping a vehicle

La palabra clave static se utiliza en un patrón de diseño Singleton. Ver enlace: https://refactoring.guru/design-patterns/singleton/php/example

El ejemplo más simple para mostrar la diferencia.
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

Late enlace estático, nota estática :: $ c

class A
{
    static $c = 7;

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

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

B::getVal(); // 8

Por ejemplo:

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();

Mirándolo desde un "¿por qué debería usar esto?" perspectiva, que es básicamente una forma de cambiar el contexto en el que se interpreta el método estático / run.

Con self, el contexto es aquel en el que ha definido el método originalmente. Con static, que es el que usted está llamando desde.

También, ver si se actualizan las variables estáticas en las clases hijas. He encontrado este resultado (un poco) inesperado donde el niño B actualizaciones niño C:

class A{
    protected static $things;
}

class B extends A {
    public static function things(){
        static::$things[1] = 'Thing B';
        return static::$things; 
    }
}

class C extends A{
    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}

print_r(C::things());
// Array (
//   [2] => Thing C
// )

B::things();

print_r(C::things()); 
// Array (
//    [2] => Thing C
//    [1] => Thing B
// )

Puede fijarlo al declarar la misma variable en cada clase de niño, por ejemplo:

class C extends A{
    protected static $things; // add this and B will not interfere!

    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top