Есть ли причина, по которой 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();
}
}