Crear instancia de clase desde el método estático


Como dice el título, quiero crear una instancia de una clase desde dentro de un método estático de la misma clase. Me he dado cuenta hasta ahora es que puedo hacer algo como esto:

class Foo{

 public $val;

 public static function bar($val){
  $inst = new Foo;
  $inst->val = $val;
  return $inst;
 }

}

Que por lo tanto me permite hacer esto.

$obj = Foo::bar("some variable");

Lo cual es genial.

Así que ahora las preguntas. ¿Hay una forma más fácil de hacer esto de la que no soy consciente, o algún atajo para lograr el mismo resultado? ¿Hay alguna ventaja o desventaja de crear una instancia en este ¿moda?

Gracias.

Author: daniel, 2011-01-11

3 answers

La forma en que lo estás haciendo está bien. Hay algunas otras cosas que pueden hacer su vida más fácil que usted puede hacer también.

  1. No codifique el nombre de la clase. Si estás en 5.3+, usa la palabra clave static. De esa manera, si extiende la clase, la nueva función puede instanciar esa también:

    public static function bar($var) {
        $obj = new static();
        $obj->var = $var;
        return $obj;
    }
    

    Entonces puede usarlo en cualquier clase extendida sin necesidad de sobrescribir nada.

  2. Averiguar si $var se debe pasar a través de un constructor en lugar de establecer después de la construcción. Si el objeto depende de él, debe requerirlo.

    public function __construct($var) {
        $this->var = $var;
    }
    

    De esta manera no se puede crear una instancia del objeto sin establecer la variable.

  3. Aplique la instanciación de la clase a través del método estático. Si estás haciendo algo allí que necesitas hacer, entonces haz que el constructor sea protegido o privado. De esa manera, alguien no puede eludir el método estático.

    protected function __construct() {}
    private function __construct() {}
    

Espero que ayudar...

Edit: Basado en su comentario anterior, me parece que está tratando de implementar el Patrón de Diseño Único . Hay toneladas de información por ahí sobre por qué no es una gran idea y las cosas malas que puede hacer. Tiene usos también.

Pero hay algunos otros patrones que pueden ser de utilidad para usted dependiendo de lo que está haciendo exactamente.

  • Puede usar el Método de Fábrica si está tratando de crear diferentes objetos con los mismos pasos.
  • Si todos los objetos comienzan igual y luego se personalizan, podría usar el Patrón de prototipo .
  • Podría usar un Grupo de objetos si es particularmente costoso crear su objeto.

Pero una cosa a considerar, es que en PHP los objetos son bastante ligeros. No intente evitar crear un nuevo objeto solo por esa sobrecarga. Evite hacer cosas pesadas como consultas de base de datos o accesos al sistema de archivos varias veces. Pero no te preocupes por llamar a new Foo() a menos que el constructor de foo sea particularmente pesado...

 73
Author: ircmaxell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-11 14:41:37

Esto parece un patrón de método de fábrica simple.

Tiene una buena ventaja: supongamos que en el futuro desea comenzar a usar una implementación diferente (pero que hace lo mismo). Usando una fábrica puede cambiar todos los objetos que se crean en muchos lugares de un sistema complejo simplemente cambiando el método creator. Tenga en cuenta que esto funcionaría más fácilmente si utiliza una clase externa (como se muestra en el primer enlace a continuación).

Manteniéndolo como lo ha hecho ahora, también puede subclase esta clase y sobrescribir el método para crear un objeto más complejo. No creo que esto sea lo que quieres lograr aquí.

De todos modos, esto es bueno para permitir el Desarrollo impulsado por pruebas, la abstracción y muchas otras cosas buenas.

Enlaces:

  1. Patrones de Php
  2. Patrón de método de fábrica en wikipedia
 3
Author: Pedro Loureiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-11 14:36:27

Si solo estás creando un objeto, esto no es muy útil. Podrías llamar a un constructor. Pero si estás haciendo algo más complicado (como si estuvieras empezando con algún tipo de patrón singleton pero no has incluido todos los detalles en este ejemplo), entonces:

Esto suena correcto. Si desea evitar que los objetos se creen de la manera predeterminada de esta manera:

$obj = new Foo("Some Variable");

Puede agregar un constructor privado:

class Foo{

 public $val;

 private __construct(){}

 public static function bar($val){
  $inst = new Foo;
  $inst->val = $val;
  return $inst;
 }
}

Ahora obligas a la gente a usar tu clase estática. El necesidad de establecer el val en la función podría haber desaparecido, por lo que incluso podría agregar el parámetro de valor a su constructor privado, pero hacer las otras cosas (que presumiblemente desea hacer, como comprobar algún tipo de patrón único) en su función 'bar'

 0
Author: Nanne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-11 14:28:07