__construct () против SameAsClassName () для конструктора в PHP - PullRequest
67 голосов
/ 20 октября 2008

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

Пример (__construct):

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

Пример (по имени):

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

Использование метода __construct (первый пример) возможно начиная с PHP 5.

Наличие метода с тем же именем, что и у класса в качестве конструктора (второй пример), возможно с версии PHP 4 до версии 7.

Ответы [ 11 ]

69 голосов
/ 20 октября 2008

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

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

parent::__construct()

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

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

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

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

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

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

20 голосов
/ 20 октября 2008

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

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

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

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

15 голосов
/ 20 октября 2008

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

10 голосов
/ 16 июня 2013

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

Переименование классов - это плохая практика: вы должны помнить, что и где переименовывать, каждый раз, когда вы обновляете до новой версии. Иногда (например, используя 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. Но это была не самая умная идея изменить именованные конструкторы.

7 голосов
/ 13 мая 2015

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

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

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

7 голосов
/ 20 октября 2008

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

3 голосов
/ 29 марта 2015

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


Так что в 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(), так как в будущем у вас будет меньше проблем с этим.

3 голосов
/ 20 октября 2008

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

2 голосов
/ 20 октября 2008

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

1 голос
/ 06 декабря 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...