Nuevo yo versus nueva estática


513

Estoy convirtiendo una biblioteca PHP 5.3 para que funcione en PHP 5.2. Lo principal que se interpone en mi camino es el uso de enlaces estáticos tardíos como return new static($options);, si convierto esto return new self($options), ¿obtendré los mismos resultados?

¿Cuál es la diferencia entre new selfy new static?

Respuestas:


890

¿obtendré los mismos resultados?

Realmente no. Sin embargo, no conozco una solución alternativa para PHP 5.2.

¿Cuál es la diferencia entre new selfy new static?

selfse refiere a la misma clase en la que la newpalabra clave se escribe realmente.

static, en los enlaces estáticos tardíos de PHP 5.3, se refiere a cualquier clase en la jerarquía en la que invocó el método.

En el siguiente ejemplo, Bhereda ambos métodos de A. La selfinvocación está vinculada Aporque se define en Ala implementación del primer método, mientras que staticestá vinculada a la clase llamada (también ver get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

tiene sentido. Creo que la mejor opción es pasar el nombre de la clase a la función que utiliza el enlace estático tardío y luego devolver el nuevo $ className ($ opciones);
Mike

12
No tiene que "pasar" el nombre de la clase, siempre puede hacerlo get_called_class(), que es efectivamente el mismo __CLASS__pero compatible con LSB.
sombra

77
get_called_class no existe en <PHP5.3. Por lo tanto, si desea obtener el nombre de clase del objeto instanciado en PHP5.2 Esta función no ayuda al intentar convertir una biblioteca de PHP 5.3 a PHP 5.2
txwikinger

2
La función llamada como self :: theFunction () se comporta como "Ejecutaré en el contexto de la clase a la que pertenezco físicamente". y la función llamada como static :: theFunction () se comporta como "Ejecutaré en el contexto de la clase que ha sido llamada por el mundo exterior". (Suponiendo el escenario de herencia). Gracias
Shubhranshu

2
En mi cabeza, simplemente tomo lo que sea intuitivo y lo opuesto. Pensarías en base a la denominación, selfregresaría a sí mismo y staticdevolvería algo que no puede ser anulado ... Pero mira y es todo lo contrario. Nunca dejo de sentirme impresionado por los nombres, las convenciones y el estilo general de PHP. -_-
ahnbizcad

23

Si el método de este código no es estático, puede obtener una solución en 5.2 utilizando get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Los resultados:

string(1) "B"
string(1) "B"

17
Si el método no es estático, los enlaces estáticos tardíos se vuelven totalmente irrelevantes.
BoltClock

1
Por ejemplo, podría usarlo en el método de "copia", donde el objeto se copia sin usar clone, pero simplemente recreando y configurando las propiedades. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis

99
@BoltClock ¿Seguramente no? Si está llamando a un método estático anulado desde un método de instancia de una subclase, entonces su elección self::o static::afectará si se utiliza la versión de la clase base o la subclase de ese método estático. En ausencia de alguna razón para pensar que tal situación ocurra inherentemente indica mala práctica (y no veo ninguna razón por la cual esto sea así), la elección entre self::y static::es tan relevante dentro de los métodos no estáticos como lo es en métodos estáticos ¿He entendido mal su comentario, o uno de nosotros simplemente está equivocado?
Mark Amery

44
@ Mark Amery: Hmm, no pensé en eso. Estás absolutamente en lo correcto. Supuse que no se llamarían métodos estáticos en el método de instancia en cuestión, pero según su ejemplo, puedo ver cómo sería una suposición muy ingenua.
BoltClock


7

Además de las respuestas de otros:

static :: se calculará utilizando información de tiempo de ejecución.

Eso significa que no puede usar static::en una propiedad de clase porque los valores de las propiedades:

Debe poder evaluarse en tiempo de compilación y no debe depender de la información de tiempo de ejecución.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Utilizando self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Tenga en cuenta que el comentario de error fatal en el código que hice no indica dónde ocurrió el error, el error ocurrió antes de que el objeto se instanciara como @Grapestain mencionado en los comentarios


44
Tenga en cuenta que el error se produce en la línea 2 public $name = static::class;, no en la línea 7, como sugiere el ejemplo. El error dice: "la clase static :: no se puede usar para la resolución del nombre de la clase en tiempo de compilación", lo que indica que el problema no es donde intenta acceder al campo $ name, sino mucho antes, en la compilación de la clase PHP. La línea 7 (o 6) no se alcanzará en el primer ejemplo.
sbnc.eu

@Grapestain El comentario que hice en el ejemplo fue mostrar el resultado final y no indicar dónde ocurrió realmente el error. Pero de todos modos, gracias por señalar eso.
Lluvia

Bien, no quise criticar, solo clarifiqué lo que me confundió primero con la esperanza de que pueda ayudar a otros. Ejemplo útil de todos modos!
sbnc.eu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.