¿Hay otra forma de crear un objeto con un nombre de clase devuelto por un método?

Tengo este método:

public function getInstance()
{
    $classname = $this->getFullyQualifiedClassName();
    return new $classname();
}

¿Hay alguna manera de escribir esto sin el $classname variable, que se usa solo una vez?

preguntado el 08 de noviembre de 11 a las 10:11

No hay nada de malo en hacerlo con $ classname. Si desea una instanciación de clase a partir de una variable de cadena, realmente no tiene otra opción. O podrías hacer una fábrica con una declaración huuuuuge if -

@inkubux: "No, no hay manera (al menos no hay manera más corta)" sería una respuesta perfectamente buena, siempre que pueda citar alguna fuente oficial que demuestre que "Realmente no tengo la opción". Si puede, hágalo, sin duda aceptaré su respuesta. La cosa es que busqué en Google y no encontré nada interesante, por lo que esta pregunta podría ser una buena referencia. -

Su ejemplo está usando la variable dos veces: primero para una asignación, luego para el acceso. Si se usara solo una vez, luego no lo necesitas, pero lo usas dos veces y eso está muy bien y hace que su código sea más legible, lo que is importante. Entonces yo diría que no tienes ningún problema aquí. -

@hakre: Por usado me refería visitada, pero creo que ya lo sabes, ¿no? Sin embargo, tu otra oración hace que tu comentario no sea completamente inútil ... -

@ greg0ire:;) Necesitaba trazar una línea nítida aquí (la asignación califica como uso variable para mí si la tomo estrictamente) y me ayudó a concluir con la segunda parte, que realmente es más importante que discutir sobre lo que cuenta como uso o no (que puede ser subjetivo). No encuentro su código feo de ninguna manera. Para cada línea, está claro lo que hace y la variable se ve bien nombrada. -

2 Respuestas

Podrías usar Reflexión:

$reflectionClass = new ReflectionClass('SomeClassName'); 
$reflectionClass->newInstanceArgs(array(1, 2, 3));

Pero hasta donde yo sé, será mucho más lento que la solución que ya tiene. En un mundo perfecto, podrías escribir algo como esto:

return new ( $this->getFullyQualifiedClassName() )(); // THIS DOES NOT WORK!!!

Pero, lamentablemente, la sintaxis de PHP no es muy flexible y, por lo tanto, tienes que crear esa fea variable que te preocupa.


Me acabo de dar cuenta de que hay otro (muy feo) forma de hacerlo: eval:

return eval("return new ".$this->getFullyQualifiedClassName()."();");

Sin embargo, no sugiero que hayas usado esto, debido a la riesgo de seguridad que viene con el uso de eval.

respondido 08 nov., 11:15

Me preguntaba si podría escribir algo menos feo. Intento nunca crear una variable que no se use al menos dos veces. - Greg0ire

En ese caso, su única otra opción es ReflectionClass, pero hasta donde yo sé, es órdenes de magnitud más lento que su solución inicial. - fresskoma

+1, respondiste la pregunta, eso estaba un poco mal planteado. Lo que realmente quiero es algo corto y tan eficaz como el código original, pero creo que no existe. Como dije, ciertamente aceptaría una respuesta que lo diga respaldada con evidencia de una fuente confiable. - Greg0ire

Vi que editaste tu pregunta, me quedaré con lo que sé. Una elección entre feo y más feo, supongo. - Greg0ire

Entrega tu getFullyQualifiedClassName método un parámetro ya sea objeto de retorno o cadena.

public function getFullyQualifiedClassName($return_object = false) {
    //............
    return $return_object ? new $classname() : $classname;
}

luego

public function getInstance()
{
    return $this->getFullyQualifiedClassName(true);
}

Pero creo que esta forma no es mejor que tener un $classname en tu getInstance método si tu getFullyQualifiedClassName solo necesito devolver la cadena del nombre de la clase.

Edit: Como dijo @ x3ro, viola el nombre del método, otra forma es usar un método de Ayuda, pero aún vale poco. En realidad el $classname no es tan feo.

public function getInstance()
{
    return Util::NewObjectFromName($this->getFullyQualifiedClassName());
}

respondido 08 nov., 11:15

-1 Estás devolviendo un Objeto de un método que indica (por su nombre) que devolverá un Nombre de la clase. Muy mala práctica, en mi opinión. - fresskoma

+1 por darme una solución para este problema, pero esta es una solución, no una solución. - Greg0ire

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.