Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: NewtangОтветов: 11

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

Пример (__construct):

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

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

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

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

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

phpconstructor

Ответы

Ответ 1 · рейтинг 70 · Bazman

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

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

parent::__construct()

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

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

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

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

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

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

Ответ 2 · рейтинг 20 · Paolo Bergantino

__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 не искал где-то еще.

Ответ 3 · рейтинг 15 · gizmo

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

Ответ 4 · рейтинг 10 · Jan Turoň

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

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

Пример

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

Ответ 5 · рейтинг 7 · Ryan McCue

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

Ответ 6 · рейтинг 7 · Levi Morrison

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

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

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

Ответ 7 · рейтинг 3 · Steven Oxley

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

Ответ 8 · рейтинг 3 · Rizier123

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

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

Ответ 9 · рейтинг 2 · Jeremy Privett

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

Ответ 10 · рейтинг 1 · phvish

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

Ответ 11 · Leonardo Molina

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы