Подтвердить что ты не робот

Почему у Magento есть методы _construct и __construct?

Есть ли причина, по которой Magento имеет метод _construct и __construct? Почему существует дополнительный _construct? Могло ли быть достигнуто то, что дополнительный метод _construct не был достигнут, просто вызвав родительский конструктор в дочернем классе?

4b9b3361

Ответ 1

Лучший ответ, который я могу найти: http://www.magentocommerce.com/boards/viewthread/76027/#t282659

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

Скажите, что у вас есть эта настройка:

class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
       doSomethingReallyImportant();
   }
}

class SubClass extends BaseClass {
   function __construct() {
       print "In SubClass constructor\n";
   }
}

$obj = new BaseClass();
//"In BaseClass constructor"
//something really important happens

$obj = new SubClass();
//"In SubClass constructor"
//important thing DOESN'T happen

PHP автоматически не вызывает конструкторы родительского класса, поэтому doSomethingReallyImportant никогда не вызывается. Вы можете потребовать, чтобы конструкторы подкласса вызывали parent::__construct(), но это было легко забыть. Итак, Magento имеет подклассы переопределить _construct:

class BaseClass {
   function __construct() {
       doSomethingReallyImportant();
      _construct();
   }
   function _construct() {
       print "In BaseClass constructor\n";
   }
}

class SubClass extends BaseClass {
   function _construct() {
       print "In SubClass constructor\n";
   }
}

$obj = new BaseClass();
//something really important happens
//"In BaseClass constructor"

$obj = new SubClass();
//something really important happens
//"In SubClass constructor"

PHP не обнаруживает конструктор в SubClass, поэтому он вызывает конструктор BaseClass. Это позволяет BaseClass до doSomethingReallyImportant перед вызовом переопределенного SubClass _construct.

Ответ 2

Марко: неправильно переопределить метод __construct(), подобный этому в Magento. Причина в том, что все классы наследуют его от Varien_Object и он имеет этот код:

#File: lib/Varien/Object.php 
public function __construct() 
{     
      //...snip...             
      $args = func_get_args();     
      if (empty($args[0])) 
      {         
          $args[0] = array();     
      }     
      //...snip... 
} 
//... 

С помощью __construct, использующего ваш код, эти аргументы не проходят. Вам действительно нужно использовать код Benesch:

class SubClass extends BaseClass {
   function _construct() {
       print "In SubClass constructor\n";
   }
}

Подробнее об этом читайте в Методы жизненного цикла Magento Block от Alan Storm

Ответ 3

Изменить: извините, пропустил разницу между _construct и __construct в вашем вопросе. Я думаю, что программисты Magento попытались упростить переопределение конструктора без риска того, что их собственный конструктор больше не будет вызван. Метод _construct в Varien_Object пуст, поэтому не имеет значения, не вызван ли он из подклассов.


Именно так PHP реализует конструкторы и деструкторы для классов. В этом нет ничего особенного в Magento.

В других языках конструктор обычно реализуется с помощью метода, имеющего то же имя, что и сам класс, и у конструктора обычно есть тильда (~) перед именем метода, которое имеет то же имя, что и класс. По какой-то причине люди PHP реализовали его таким образом, хотя PHP также, похоже, поддерживает конструкторы и деструкторы с именем класса (ссылка).

Класс не должен иметь конструктор и/или деструктор, особенно если вы подклассифицируете другой класс. Если вы переопределите конструктор или деструктор, вам нужно вызвать конструктор или деструктор переопределенного класса вручную, вызвав его на parent::, например:

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       // Your code
   }
   function __destruct() {
       // Your code
       parent::__destruct();
   }
}