¿Cuál es la diferencia entre usar self
y static
en el siguiente ejemplo?
class Foo
{
protected static $bar = 1234;
public static function instance()
{
echo self::$bar;
echo "\n";
echo static::$bar;
}
}
Foo::instance();
produce
1234
1234
Respuestas:
Cuando usa
self
para referirse a un miembro de la clase, se está refiriendo a la clase dentro de la cual usa la palabra clave. En este caso, suFoo
clase define una propiedad estática protegida llamada$bar
. Cuando usaself
en laFoo
clase para hacer referencia a la propiedad, hace referencia a la misma clase.Por lo tanto, si intentó usar
self::$bar
en otra parte de suFoo
clase, pero tenía unaBar
clase con un valor diferente para la propiedad, usaría enFoo::$bar
lugar deBar::$bar
, que puede no ser lo que pretende:Cuando llamas a un método a través de
static
, estás invocando una función llamada enlaces estáticos tardíos (introducidos en PHP 5.3).En el escenario anterior, el uso
self
resultará enFoo::$bar
(1234). Y el usostatic
resultará enBar::$bar
(4321) porque constatic
, el intérprete tiene en cuenta la redeclaración dentro de laBar
clase durante el tiempo de ejecución.Por lo general, utiliza enlaces estáticos tardíos para métodos o incluso para la propia clase, en lugar de propiedades, ya que no suele volver a declarar propiedades en subclases; un ejemplo del uso de la
static
palabra clave para invocar un constructor de enlace tardío se puede encontrar en esta pregunta relacionada: New self vs new staticSin embargo, eso no excluye el uso también
static
con propiedades.fuente
<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
self::$abc
cuando se usa en el interiorclass Foo
es lo mismo que decirFoo::$abc
. No se verá afectado por ninguna nueva declaración de$abc
en una subclase. AFAIK, la única razón para usarself
es como una abreviatura, para evitar usar el nombre de la claseFoo
, que puede ser más largo. [También significa que puede cambiar el nombre de la clase sin cambiar todos esos lugares, pero esa no es una gran razón en mi humilde opinión.] (La elección de nombres de PHP es desafortunada y parece al revés; "estático" es el que puede cambiar, lo cual es opuesto al significado coloquial de la palabra en lenguaje natural "estático".)Como se mencionó, una de las principales diferencias es que
static
permite enlaces estáticos tardíos. Uno de los escenarios más útiles que encontré fue el de crear clases base para clases Singleton:El uso
return static::$name
en la clase Base devolverá lo que se adjuntó estáticamente cuando se extendió. Si se va a utilizarreturn self::$name
a continuación,B::getName()
se devolverá una cadena vacía, ya que es lo que se declaró en la clase base.fuente
Con
self
llamada:Puede ver arriba, aunque hemos anulado el
$var
con nuestraBar
clase, todavía regresa123
, porque le hemos pedido explícitamente a PHP laself
variable, que a su vez solicitaFoo
la variable s en su lugar.Ahora, si intercambiamos la llamada con
static
, obtendremosBar
un valor anulado:Con
static
llamada:fuente