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

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

пример:

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

ИЛИ

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

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

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

 parent::__construct() 

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

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

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

Также отметим, что

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

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

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

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

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

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

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

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

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

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

пример

 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. Но не самая умная идея изменить именованные конструкторы.

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

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

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

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

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

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

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

Таким образом, в 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 __construct() .

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

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

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

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

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

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