2011-01-26 16 views
5

¿Hay una manera de evitar la creación de objetos dentro de su constructor, de manera que:Rompiendo el constructor

$object = new Foo(); 
echo $object; // outputs: NULL 
+0

posible duplicado de [PHP constructor para devolver un NULL.] (Http://stackoverflow.com/questions/2214724/php-constructor-to-return-a-null) –

Respuesta

13

No, no es posible; la palabra clave newalways devuelve una instancia de la clase especificada, independientemente de lo que intente devolver desde el constructor. Esto se debe a que cuando se llama a su constructor, PHP ya ha terminado de asignar memoria para el nuevo objeto. En otras palabras, el objeto ya existe en ese punto (de lo contrario, no hay ningún objeto para llamar al constructor).

Podría generar errores o arrojar excepciones del constructor en su lugar, y manejarlas en consecuencia.

class Foo { 
    public function __construct() { 
     throw new Exception('Could not finish constructing'); 
    } 
} 

try { 
    $object = new Foo(); 
} catch (Exception $e) { 
    echo $e->getMessage(); 
} 
+3

@Gordon: Sí, lo escribí mal, gracias; es la palabra clave 'new' que realmente crea la instancia; es durante la asignación de este objeto que PHP llama '__construct()' si existe. – BoltClock

2

Basta con lanzar una excepción:

throw new Exception('thou shalt not be born!'); 
+0

Esto no evitará que el objeto sea creado. –

+0

Ahah! +1 por ser gracioso !! – Tivie

1

Puede implementar una fábrica para hacer la creación del objeto para usted. Si está utilizando PHP 5.3.0+, tendrá acceso a una característica denominada Enlace estático tardío que lo hace fácil.

<?php 
class MyObject 
{ 
    protected $loadSuccess = false; 

    protected function __construct ($foo, $bar, $baz) 
    { 
     // Just a random 50/50 success probability. Put real logic for testing success here 
     $this -> loadSuccess = (mt_rand (0, 99) > 49); 
    } 

    static public function factory ($foo, $bar, $baz) 
    { 
     $objClass = get_called_class(); 
     $obj = new $objClass ($foo, $bar, $baz); 
     if ($obj -> loadSuccess) 
     { 
      return ($obj); 
     } 
    } 
} 

class MySubClass extends MyObject 
{ 
    protected function __construct ($foo, $bar, $baz) 
    { 
     parent::__construct ($foo, $bar, $baz); 
     if ($this -> loadSuccess) 
     { 
      echo ('Hello, I\'m a ' . get_called_class() . '<br>'); 
     } 
    } 
} 

class MySubSubClass extends MySubClass 
{ 
    protected function __construct ($foo, $bar, $baz) 
    { 
     parent::__construct ($foo, $bar, $baz); 
     if ($this -> loadSuccess) 
     { 
      echo ($foo * $bar * $baz . '<br>'); 
     } 
    } 
} 

$o1 = MyObject::factory (1, 2, 3); // Base class 
$o2 = MySubClass::factory (4, 5, 6); // Child class 
$o3 = MySubSubClass::factory(7, 8, 9); // Descendent class 

var_dump ($o1); 
var_dump ($o2); 
var_dump ($o3); 
?> 

Si está utilizando una versión de PHP 5.3.0 antes de entonces las cosas se ponen un poco más complicado de lo más tarde get_called_class unión y estático() no están disponibles. Sin embargo, PHP 5 admite la reflexión y puede usarlo para emular la vinculación estática tardía. De forma alternativa, puede implementar una clase de fábrica separada y pasarle un argumento indicándole qué tipo de objeto desea inicializar.

Otro enfoque es hacer que su constructor genere una excepción si falla y manejarla con un bloque catch. Sin embargo, este método puede ser bastante complicado si lo haces mucho y solo debería usarse cuando normalmente esperas que la creación de objetos tenga éxito (en otras palabras, si el error de creación es una circunstancia excepcional).

El enfoque de fábrica tiene ventajas adicionales, por ejemplo, puede contener un caché de objetos que ya ha creado y si intenta crear el mismo objeto dos veces simplemente le pasará una referencia al objeto ya inicializado en lugar de creando uno nuevo. Esto elimina la sobrecarga de memoria y procesamiento inherente en la creación de objetos, especialmente si la creación implica una tarea que exige mucho tiempo, como una consulta SQL compleja

0

Si intenta detener la instancia de un objeto dependiendo de unas pocas condiciones, entonces ¿por qué no crear una condición antes de siquiera golpear el PHP new y crear una instancia de la clase?

Lo que quiero decir es, dicen en su ejemplo:

$object = new Foo(); 
echo $object; // outputs: NULL 

Usted podría envolverlo en una función que hace el trabajo de validación para usted o simplemente una sentencia if Si sólo va a crear una instancia de la clase una vez .

De esta manera:

if(conditions_to_meet){ 
    $object = new Foo(); 
} 
else $object = NULL; 

si necesita crear una instancia que múltiples veces y luego envolverlo en una función y pasar los parámetros a su clase.

Espero que esto ayude.

Cuestiones relacionadas