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

StackOverflow https://stackoverflow.com/questions/217618

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Пример (__construct):

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

Пример (именованный):

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

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

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

Это было полезно?

Решение

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

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

parent::__construct()

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

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

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

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

  

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лучшее преимущество использования __ contruct () вместо ClassName () - при расширении классов. Гораздо проще вызывать parent :: __ construct () вместо 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, если вы определяете метод с тем же именем, что и класс, И __construct().

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

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


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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top