Есть ли причина, по которой Magento имеет метод _construct и __construct? Почему существует дополнительный _construct? Могло ли быть достигнуто то, что дополнительный метод _construct не был достигнут, просто вызвав родительский конструктор в дочернем классе?
Почему у Magento есть методы _construct и __construct?
Ответ 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();
}
}