Конструктор, возвращающий значение?

21

Глядя на следующий код, я вижу, что конструктор возвращает значение. Я думал, что конструкторы только возвращают объекты. Может кто-нибудь сказать мне, что мне не хватает?

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;
        }
    }
    
задан Nate 10.08.2012 в 16:55
источник
  • Я не думаю, что конструкторы возвращают объекты: я считаю, что PHP создает экземпляр данного класса, а затем вызывает его конструктор, прежде чем пользователь сможет что-либо сделать. –  Waleed Khan 10.08.2012 в 16:57
  • Спасибо за исправление. После повторного чтения моего сообщения я искал комментарий, чтобы точно сказать, что вы разместили :) –  Nate 10.08.2012 в 17:05

5 ответов

38

Действительно, вы правы. Ничего нельзя сделать с возвращаемым значением конструктора (кроме использования созданного им объекта).

Так что нет, вы ничего не упускаете, это разработчик, который написал этот код.

Технически возможно использовать возвращаемые значения из конструкторов, если вы вызываете функцию напрямую

$obj->__construct();

Это позволит вам использовать возвращаемое значение конструктора. Тем не менее, это очень редко и довольно не рекомендуется.

    
ответ дан Madara Uchiha 10.08.2012 в 16:58
  • На самом деле, технически это возможно: codepad.org/sh94ogi9 - Вам просто нужно вызвать функцию напрямую, а не через новую. Это требует, чтобы объект уже существовал естественным образом. –  hakre 10.08.2012 в 17:06
  • @hakra: Да, но ОП задал вопрос о конструкторах в смысле создания новых объектов. Я добавлю это к ответу. –  Madara Uchiha♦ 10.08.2012 в 17:08
  • Технически возможно близко к nitpickydidodida, я просто хотел подслушать, слишком поздно для ответа. :) –  hakre 10.08.2012 в 17:15
12

Ответы, данные до сих пор, неверны. С возвращаемым значением конструктора вы можете делать все, что захотите, поэтому неверно, что «ничего нельзя сделать с возвращаемым значением конструктора (кроме использования созданного им объекта)». Возвращаемое значение конструктора не является созданным объектом «оно». Конструктор не создает объекты (ключевое слово 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 состоит в том, что родительский класс не является абстрактным, но сам может быть создан, но в этом контексте возвращенные сообщения об ошибках никогда не будут видны. Итак, плохая картина; плохой. Конструкторы не предназначены для возврата значений, что означает, что вы открываете архитектурную банку червей, используя этот механизм.

    
ответ дан Vladimir Kornea 13.01.2014 в 20:30
4

см. этот URL - Возврат значения в конструкторе функция класса

Прочтите: -

Конструкторы не получают возвращаемые значения; они служат исключительно для создания экземпляра класса.

Без реструктуризации того, что вы уже делаете, вы можете рассмотреть возможность использования исключения здесь.

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
}
    
ответ дан Abid Hussain 10.08.2012 в 17:01
1

Конструктор ничего не возвращает, но вы можете вернуться из него (по какой-то причине выполнение метода останавливается, но объект может быть создан).

    
ответ дан Peter Kiss 10.08.2012 в 16:58
0

В отличие от других языков, в PHP вы можете явно вызывать конструктор. Это просто другая функция. Похоже, что первоначальный автор сначала решил поместить в конструктор некоторый код, который может не работать, а затем понял, что ему нужен способ перезапустить инициализацию после сбоя.

$result = $user->__construct($username, $password)

будет работать, и вы получите возвращаемое значение. Это уродливый способ делать вещи, очевидно.

На мой взгляд, не рекомендуется использовать код, вызывающий побочные эффекты в конструкторе. Я бы поместил код в отдельную функцию с именем, в котором четко указано, что он делает.

    
ответ дан cleong 10.08.2012 в 17:25