¿Qué significa nuevo yo (); significa en PHP?


110

Nunca había visto un código como este:

public static function getInstance()
{
    if ( ! isset(self::$_instance)) {
        self::$_instance = new self();
    }
    return self::$_instance;
}

¿Es lo mismo que new className()?

EDITAR

Si la clase es heredada, ¿a qué clase apunta?



@ stereofrog, ¿quieres decir que el patrón singleton debería abandonarse? Pero todas las cosas existen por una razón, ¿verdad?
user198729

Oh, tiendo a estar de acuerdo con este punto: singleton debe ser reemplazado por la fábrica
user198729

@stereofrog Los Singleton son venenosos para las pruebas unitarias, es extremadamente difícil hacer pruebas inmutables en algo que cambia de estado de una llamada a la siguiente.
David

Desafortunadamente, este método no se extenderá. Siempre le dará un nuevo objeto de la clase en la que se definió esta función.
Ares

Respuestas:


211

self apunta a la clase en la que está escrito.

Entonces, si su método getInstance está en un nombre de clase MyClass, la siguiente línea:

self::$_instance = new self();

Hará lo mismo que:

self::$_instance = new MyClass();



Editar: un par de informaciones más, después de los comentarios.

Si tienes dos clases que se extienden entre sí, tienes dos situaciones:

  • getInstance está definido en la clase secundaria
  • getInstance está definido en la clase padre

La primera situación se vería así (eliminé todo el código no necesario, para este ejemplo, tendrá que volver a agregarlo para obtener el comportamiento singleton) *:

class MyParentClass {

}
class MyChildClass extends MyParentClass {
    public static function getInstance() {
        return new self();
    }
}

$a = MyChildClass::getInstance();
var_dump($a);

Aquí obtendrás:

object(MyChildClass)#1 (0) { } 

Lo que significa selfsignifica MyChildClass, es decir, la clase en la que está escrito.


Para la segunda situación, el código se vería así:

class MyParentClass {
    public static function getInstance() {
        return new self();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Y obtendría este tipo de resultado:

object(MyParentClass)#1 (0) { }

Lo que significa selfsignifica MyParentClass, es decir, aquí también, la clase en la que está escrito .




Con PHP <5.3, esa "clase en la que está escrito" es importante y, a veces, puede causar problemas.

Es por eso que PHP 5.3 introduce un nuevo uso para la staticpalabra clave: ahora se puede usar exactamente donde la usamos selfen esos ejemplos:

class MyParentClass {
    public static function getInstance() {
        return new static();
    }
}
class MyChildClass extends MyParentClass {

}

$a = MyChildClass::getInstance();
var_dump($a);

Pero, con en staticlugar de self, ahora obtendrás:

object(MyChildClass)#1 (0) { } 

Lo que significa que staticapunta a la clase que se usa (usamos MyChildClass::getInstance()), y no a la clase en la que está escrito.

Por supuesto, el comportamiento de selfno se ha cambiado, para no romper las aplicaciones existentes - PHP 5.3 acaba de agregar un nuevo comportamiento, reciclando la staticpalabra clave.


Y, hablando de PHP 5.3, es posible que desee echar un vistazo a la página Late Static Bindings del manual de PHP.


@Paul: heu ... quería decir "self actúa como un alias para", o "self apunta a" - el verbo "diseñador", en francés, puede usarse para eso - supongo que esa es una de las situaciones en el que usar la misma palabra en inglés no es una buena idea ;-( Editaré mi respuesta para arreglar esto ;; gracias :-)
Pascal MARTIN

¿Y si hay baseclass, classque uno tiene que apunte a?
user198729

@user: He editado mi respuesta para dar un poco más de información sobre la selfherencia; y también he incluido información sobre staticPHP 5.3 ;; espero que esto ayude :-)
Pascal MARTIN

10

Esto parece ser una implementación del patrón Singleton . La función se llama estáticamente y comprueba si la clase estática tiene la variable $_instanceestablecida.

Si no es así, inicializa una instancia de sí mismo ( new self()) y la almacena en $_instance.

Si llama className::getInstance(), obtendrá una y la misma instancia de clase en cada llamada, que es el punto del patrón singleton.

Sin embargo, nunca lo había visto así hecho de esta manera y, sinceramente, no sabía que fuera posible. ¿Qué se $_instancedeclara como en la clase?


1
$_instancese declara comopublic static $_instance;
Atif

7

Es muy probable que esto se use en el patrón de diseño singleton, donde el constructor se define como privado para evitar ser instanciado, el (::)operador de dos puntos puede acceder a los miembros que se declaran estáticos dentro de la clase, por lo que si hay miembros estáticos, la pseudo variable $ esto no se puede usar, por lo tanto, el código se usó en su lugar, los Singleton son buenas prácticas de programación que solo permitirán 1 instancia de un objeto, como los controladores de conectores de bases de datos. Desde el código del cliente, acceder a esa instancia se haría creando un único punto de acceso, en este caso lo nombró getInstance(), La getInstance en sí misma fue la función que creó el objeto básicamente usando la nueva palabra clave para crear un objeto, lo que significa que el método constructor fue también llamado.

la línea if(!isset(self::instance))verifica si ya se ha creado un objeto, no podría entender esto porque el código es solo un fragmento, en algún lugar en la parte superior, debería haber miembros estáticos como probablemente

private static $_instance = NULL; 

en clases normales habríamos accedido a este miembro simplemente

$this->_instance = 'something';

pero está declarado estático y por eso no podemos usar el código $ this que usamos en su lugar

self::$_instance

al verificar si hay un objeto almacenado en esta variable de clase estática, la clase puede decidir crear o no crear una sola instancia, por lo que si no está configurado,! isset, lo que significa que no existe ningún objeto en el miembro estático $ _instance, entonces genera un nuevo objeto, lo almacena en el miembro estático $_instancepor el comando

self::$_instance = new self();

y lo devolvió al código del cliente. El código del cliente puede usar felizmente la instancia única del objeto con sus métodos públicos, pero en el código del cliente, llamando al punto de acceso único, es decir, el getInstance()método también es complicado, debe llamarse así.

$thisObject = className::getInstance();

la razón, la función en sí misma se declara estática.


2

Sí, es como new className()(refiriéndose a la clase que contiene ese método), probablemente usado en un patrón Singleton donde el constructor es privado.


¿Por qué alguien usaría el patrón Singleton en PHP? A menos que se use en un programa similar a un demonio, el singleton solo vivirá mientras se ejecuta el script y luego desaparecerá junto con el programa.
ILikeTacos

4
para evitar declarar irritantemente global para acceder a una variable global
Sam Adamsh

0

Si la clase se hereda, llamar a getInstance () desde niño no le dará una instancia de niño. Solo devolverá una instancia de la instancia principal. Esto se debe a que llamamos nuevo yo ().

Si desea que la clase secundaria devuelva una instancia de la clase secundaria, utilice new static () en getInstance () y luego devolverá la instancia de la clase secundaria. ¡Esto se llama enlace tardío!

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.