2011-01-26 60 views
5

有沒有一種方法,以防止它的構造函數中創建對象,因此:打破構造

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

[PHP構造函數返回NULL。]的可能的重複(http://stackoverflow.com/questions/2214724/php-constructor-to-return-a-null) – 2011-01-26 11:12:58

回答

13

不,不可能的; new關鍵字總是返回指定類的實例,無論您嘗試從構造函數返回什麼。這是因爲在調用構造函數時,PHP已經完成爲新對象分配內存。換句話說,該對象已經存在於此點(否則,根本就沒有對象可以調用構造函數)。

您可以引發錯誤或從構造函數中拋出異常,並相應地處理這些異常。

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

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

簡單地拋出一個異常:

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

這不會阻止對象從存在創建。 – 2011-01-26 11:12:08

+0

啊哈!有趣的+1! – Tivie 2012-07-23 00:49:32

1

你可以實現一個工廠來爲你做對象創建。如果您使用的是PHP 5.3.0以上版本,那麼您將可以訪問一個名爲Late Static Binding的功能,從而使這一切變得簡單。

<?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); 
?> 

如果您使用的是PHP版本的5.3.0版本之前然後事情變得有點複雜遲靜態綁定和get_called_class()不可用。但是,PHP 5支持反射,您可以使用它來模擬晚期靜態綁定。或者,你可以實現一個單獨的工廠類,並向它傳遞一個參數,告訴它你想要初始化什麼樣的對象。

另一種方法是讓你的構造函數在失敗時拋出異常,並用catch塊處理它。然而,如果你做了很多事情,這種方法會變得多毛,只有當你通常期望對象創建成功時(換句話說,如果創建失敗是一種特殊情況),這種方法纔會被使用。

工廠方法有其他優點,例如它可以容納已經創建的對象的緩存,並且如果您嘗試兩次創建相同的對象,它只會向您傳遞一個引用已經初始化的對象,而不是創造一個新的。這消除了對象創建時固有的內存和處理開銷,尤其是在創建過程涉及諸如複雜SQL查詢之類的時間密集型任務時。

0

如果嘗試根據幾個條件停止實例化對象,那麼爲什麼不創建一個條件之前,你甚至打PHP new並實例化類?

我的意思是,說在你的榜樣:

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

你可以在做驗證工作,對您或只是簡單的if語句,如果你只是要實例化的類,一旦一個函數把它包。

像這樣:

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

,如果您需要到多次實例化,然後在一個函數把它包裝和參數傳遞給你的類。

希望這會有所幫助。