__construct() vs SameAsClassName() для конструктора в PHP

Есть ли какое-либо преимущество в использовании __construct() вместо имени класса для конструктора в PHP?

Пример:

class Foo {
    function __construct(){
        //do stuff
    }
}

ИЛИ

class Foo {
    function Foo(){
        //do stuff
    }
}

Ответ 1

Я согласен с gizmo, преимущество заключается в том, что вам не нужно переименовывать его, если вы переименуете свой класс. DRY.

Аналогично, если у вас есть дочерний класс, вы можете вызвать

parent::__construct()

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

Похоже, что это небольшая вещь, но отсутствие изменения имени вызова конструктора для классов ваших родителей может создать тонкие (и не очень тонкие) ошибки.

Например, если вы вставили класс в свой heirachy, но забыли изменить вызовы конструктора, вы могли бы начать вызывать конструкторы бабушек и дедушек вместо родителей. Это может часто приводить к нежелательным результатам, которые могут быть трудно заметить.

Также обратите внимание, что

Как и в случае PHP 5.3.3, методы с тем же именем, что и последний элемент имени пространства имен, больше не будут рассматриваться как конструктор. Это изменение не влияет на классы, не содержащие имен.

Источник: http://php.net/manual/en/language.oop5.decon.php

Ответ 2

__construct был введен в PHP5. Это то, как вы должны это делать сейчас. Однако я не знаю никаких преимуществ как таковых.

Из руководства по PHP:

Для обратной совместимости, если PHP 5 не может найти функцию __construct() для данного класса, он будет искать функцию конструктора старого стиля по имени класса. Фактически это означает, что единственным случаем, который имел бы проблемы совместимости, является то, что у класса был метод с именем __construct(), который использовался для различной семантики

Если вы на PHP5, я бы рекомендовал использовать __construct, чтобы избежать появления PHP в другом месте.

Ответ 3

Основное преимущество, которое я вижу для __construct, заключается в том, что вам не нужно переименовывать свой конструктор, если вы меняете имя класса.

Ответ 4

Сегодня принятый ответ устарел.

Переименование классов - это плохая практика: вы должны помнить, что и где переименовывать каждый раз при обновлении до более новой версии. Иногда (например, используя Reflection или сложную структуру зависимостей) это невозможно без радикального рефакторинга. И это случайная сложность, которую вы хотите избежать. Вот почему пространства имен были добавлены в PHP. Java, С++ или С# не используют __construct, они используют именованный конструктор, и нет проблем с ними.

Начиная с PHP 5.3.3, методы с тем же именем, что и последний элемент имени класса namespaced, больше не будут рассматриваться как конструктор. Это изменение не влияет на классы, не содержащие имен.

Пример

namespace Foo;
class Test {
  var $a = 3;

  function Test($a) {
    $this->a = $a;
  }

  function getA() {
    return $this->a;
  }
}

$test = new Test(4);
echo $test->getA(); // 3, Test is not a constructor, just ordinary function

Обратите внимание, что именованные конструкторы не устарели (PHP 5.5 сегодня). Однако вы не можете предсказать, что ваш класс не будет использоваться в пространстве имен, , поэтому __construct должен быть выбран.

Разъяснение плохой практики, упомянутой выше (для Денниса)

Где-то в вашем коде вы можете использовать ReflectionClass:: getName(); когда вы переименовываете класс, вам нужно запомнить, где вы использовали Reflection, и проверить, является ли результат getName() по-прежнему непротиворечивым в вашем приложении. Чем больше вам нужно помнить что-то конкретное, тем более вероятно что-то забыто, что приводит к ошибкам в приложении.

Родители не могут контролировать все классы в мире, которые зависят от них. Если allow_url_include включен, некоторые другие веб-сайты могут использовать класс с вашего сервера, что может привести к сбою при переименовании какого-либо класса. Это еще хуже в компилируемых языках, упомянутых выше: библиотека может быть скопирована и добавлена ​​в другой код.

Нет причин для переименования класса:

  • Если конфликтует имя класса, используйте пространства имен
  • если ответственность за класс смещается, выведите другой класс вместо

В классах PHP в пространстве имен метод с тем же именем следует избегать: интуитивно он должен создать объект, созданный классом; если он делает что-то еще, зачем давать ему одно и то же имя? Это должен быть конструктор и ничего больше. Основная проблема заключается в том, что поведение такого метода зависит от использования пространства имен.

Нет проблем с конструкторами __construct в PHP. Но не самая умная идея изменить именованные конструкторы.

Ответ 5

Лучшим преимуществом использования __contruct() вместо ClassName() является расширение классов. Гораздо проще называть parent::__construct() вместо parent::ClassName(), так как он многократно используется среди классов, и родительский элемент может быть легко изменен.

Ответ 6

В вашем примере Foo::Foo иногда называют конструктором PHP 4 или старого стиля, поскольку он исходит из дней PHP 4:

class Foo {
    // PHP 4 constructor
    function Foo(){
        //do stuff
    }
}

PHP 4 конструкторы будут устаревать, но не удаляться в PHP 7. Они больше не будут рассматриваться как конструкторы в любой ситуации в PHP 8 Будущая совместимость, безусловно, является большой причиной не использовать эту функцию.

Ответ 7

В PHP 5 преимущество было бы в том, что производительность будет лучше. Сначала он будет искать конструктор с именем __construct, и если он его не найдет, он будет искать конструкторы по имени className. Поэтому, если он находит конструктор по имени __construct, ему не нужно искать конструктор по имени className.

Ответ 8

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

Ответ 9

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


Итак, в php-7 они удаляют параметр для создания конструктора как функции с тем же именем, что и класс. Если вы все еще это сделаете, вы получите E_DEPRECATED.

Вы можете узнать больше об этом предложении (предложение принято) здесь:  https://wiki.php.net/rfc/remove_php4_constructors

И цитата оттуда:

PHP 7 будет генерировать E_DEPRECATED, если определен конструктор PHP 4. Когда имя метода совпадает с именем класса, класс не находится в пространстве имен, а конструктор PHP 5 (__construct) отсутствует, тогда будет испускаться E_DEPRECATED. PHP 8 перестанет выдавать E_DEPRECATED, и методы не будут распознаваться как конструкторы.

Также вы не получите E_STRICT в php-7, если вы определяете метод с тем же именем, что и класс AND a __construct().

Вы также можете увидеть это здесь:

PHP 7 также будет останавливать выдачу E_STRICT, когда присутствует метод с тем же именем, что и класс, и __construct.


Поэтому я бы рекомендовал вам использовать __construct(), так как в будущем у вас будет меньше проблем с этим.

Ответ 10

Если существуют методы __construct и SameAsClassName, то будет выполняться __construct, метод SameAsClassName будет пропущен.

Ответ 11

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

Я имею в виду, что в Objective-C вы, например, префиксеруете конструкторы с -init. Вы можете создать свой собственный конструктор, используя имя вашего класса, но почему? Есть ли причина использовать эту схему вместо языкового соглашения?