2012-08-10 146 views
17

看看下面的代碼,我看到構造函數正在返回一個值。我認爲構造函數只返回對象。有人能告訴我我錯過了什麼嗎?構造函數返回值?

public function __construct($username = null, $password = null){ 
     $urlLogin = "{$this->apiHost}/login/$username"; 

     $postData = sprintf("api_type=json&user=%s&passwd=%s", 
          $username, 
          $password); 
     $response = $this->runCurl($urlLogin, $postData); 

     if (count($response->json->errors) > 0){ 
      return "login error";  
     } else { 
      $this->modHash = $response->json->data->modhash; 
      $this->session = $response->json->data->cookie; 
      return $this->modHash; 
     } 
    } 
+4

我不認爲構造函數返回對象:我相信PHP實例化給定類的新實例,然後在用戶可以執行任何操作之前調用它的構造函數。 – 2012-08-10 14:57:36

+0

感謝您的更正。重新閱讀我的文章後,我找了一個評論,以確切地說出你發佈的內容:) – Nate 2012-08-10 15:05:14

回答

32

確實你是對的。除了使用它創建的Object之外,任何構造函數的返回值都無法完成。

所以不,你不會錯過任何東西,它是誰寫的那個代碼的開發者。

這在技術上是可以使用從構造函數返回值,如果調用函數直接

$obj->__construct(); 

這將允許您使用構造函數的返回值。但是,這是非常罕見的,並且不被推薦。

+1

其實,*技術上*這是可能的:http://codepad.org/sh94ogi9 - 你只需要直接調用函數,而不是通過'new'。這就要求對象自然存在。 – hakre 2012-08-10 15:06:12

+0

@hakra:是的,但OP從製作新對象的意義上詢問了構造函數。我會將它添加到答案中。 – 2012-08-10 15:08:40

+0

*技術上*可能接近nitpickydidodida,我只是想要加入,爲時已晚。 :) – hakre 2012-08-10 15:15:34

1

構造函數不返回任何內容,但可以從中返回(由於某種原因停止某個點的方法執行,但可以創建該對象)。

2

看到這個網址 - Returning a value in constructor function of a class

讀它: -

構造函數沒有得到返回值;他們完全服務實例化班級。

沒有重構你已經在做的事情,你可以考慮在這裏使用異常。

public function __construct ($identifier = NULL) 
{ 
    $this->emailAddress = $identifier; 
    $this->loadUser(); 
} 

private function loadUser() 
{ 
    // try to load the user 
    if (/* not able to load user */) { 
     throw new Exception('Unable to load user using identifier: ' . $this->identifier); 
    } 
} 

現在,您可以用這種方式創建一個新用戶。

try { 
    $user = new User('[email protected]'); 
} catch (Exception $e) { 
    // unable to create the user using that id, handle the exception 
} 
0

與其他語言不同,在PHP中,您可以顯式調用構造函數。這只是另一個功能。它看起來像最初的作者首先決定把一些可能在構造函數中失敗的代碼,然後意識到他需要一種方法來在失敗後重新運行初始化。 $ result = $ user - > __ construct($ username,$ password)實際上可以工作,並且您可以獲得返回值。顯然做事是一種醜陋的方式。

在我看來,讓代碼在構造函數中觸發副作用並不是一個好習慣。我會把代碼放在一個單獨的函數中,並且用一個名字來清楚地說明它的功能。

8

到目前爲止給出的答案是不正確的。你可以用構造函數的返回值做任何你想做的事情,所以不能用構造函數的返回值來完成(除了使用它創建的對象)。「構造函數的返回值不是「it」創建的對象。構造函數不會創建對象(關鍵字new)。構造函數的返回值與任何其他函數的返回值相同:您選擇返回的值。此外,爲了調用它的構造函數,對象已經存在也是錯誤的。這是完全正確的:

$parent_constructor_return_value = parent::__construct(); 

例如:

abstract class MyBase { 
    function __construct() { 
     return "Hello, world."; 
    } 
} 
class MyDerived extends MyBase { 
    function __construct() { 
     echo parent::__construct(); 
    } 
} 
new MyDerived(); // prints "Hello, world." 

雖然這是可能的,我無法想象在這將是最佳實踐的情景的。畢竟,你總是可以調用除parent::__construct()以外的方法來獲得你的價值,而你所失去的只是默默無聞。我認爲它可以作爲一種錯誤處理的方式 - 有兩種其他方式來完成相同的事情:

  1. 在父構造函數中拋出異常,並捕獲它們在派生的構造函數中。
  2. 在父構造函數中指定發生錯誤的屬性,然後檢查派生構造函數中這些屬性的狀態。

如果父構造函數中的錯誤並不例外,他可能決定讓父構造函數返回錯誤值,而不是將瞬態錯誤信息存儲爲對象屬性。當然,那麼命名父節點的方法__construct的唯一原因是父類不是抽象的,而是本身可以被實例化 - 但是在這種情況下,返回的錯誤消息將永遠不會被看到。所以,壞模式;壞。構造函數並不打算返回值,這意味着您可以通過利用這種機制來打開蠕蟲的體系結構。