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

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

Пример (__construct):

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

Пример (имя):

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

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

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


person Newtang    schedule 20.10.2008    source источник


Ответы (11)


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

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

parent::__construct()

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

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

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

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

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

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

person Bazman    schedule 20.10.2008
comment
Стиль конструктора PHP 4.x будет объявлен устаревшим в PHP 7.0 и удален в следующем основном выпуске. php.net/manual/de/ - person SimonSimCity; 21.10.2015

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

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

For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics

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

person Paolo Bergantino    schedule 20.10.2008

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

person gizmo    schedule 20.10.2008

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

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

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

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

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

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

person Jan Turoň    schedule 16.06.2013
comment
не могли бы вы переписать абзац № 2 для ясности? (один начинается с переименования .... Я не понимаю, почему переименовывать классы - это плохая практика, и почему нет проблем с Java, C, C ++ и как это относится к этому вопросу. Означает ли это, что PHP также следует использовать именованный конструктор как Java, C, C++ или есть проблемы? - person Dennis; 24.04.2014
comment
@ Деннис Смотрите мой обновленный ответ. Это имеет отношение к принятому ответу, потому что Базман неправильно указал на переименование класса: к тому времени, когда я предоставил свой ответ, у него не было точки зрения на пространства имен в его ответе, он позже скопировал его из моего ответа. Теперь он присваивает себе кредит, но ничего, это не влияет на саму информацию и никого не волнует. - person Jan Turoň; 25.04.2014

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

person Ryan McCue    schedule 20.10.2008

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

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

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

person Levi Morrison    schedule 13.05.2015

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

person Steven Oxley    schedule 20.10.2008

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


Таким образом, в 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, если вы определите метод с тем же именем, что и у класса, И __construct().

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

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


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

person Rizier123    schedule 29.03.2015
comment
@Newtang Чуть-чуть опоздал :D - person Rizier123; 30.03.2015

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

person Jeremy Privett    schedule 20.10.2008

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

person phvish    schedule 06.12.2013

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

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

person Leonardo Molina    schedule 06.06.2013