2013-06-04 3 views
0

Может ли кто-нибудь объяснить мне, почему этот код работает?Вызов родительского конструктора в дочернем классе

<?php 

class iParent 
{ 
    private $device; 
    private $browser; 

    public function __construct() 
    { 
     $this->device = 'iPad'; 
     $this->browser = 'Safari'; 
    } 

    public function getDetails() 
    { 
     return 'Device ' . $this->device . ' ' . 'Browser ' . $this->browser; 
    } 
} 

/** 
* 
*/ 
class iParentChild extends iParent 
{ 
    public function __construct() 
    { 
    echo 'IParentChild constructor'; 
    } 

    public function display() 
    { 
     return $this->getDetails(); 
    } 
} 

$obj = new iParentChild; 
echo $obj->display(); 

// Output 
Device iPad Browser Safari 

Я думал, что он должен работать только тогда, когда я называю parent::__construct() (инициализировать родительский конструктор) в конструкторе iParentChild.

// UPDATE Я добавил __construct в iParentChild

+1

В чем заключается путаница? Вы не указали конструктор 'iParentChild', поэтому он наследует один из родительского класса. Это так просто. –

ответ

1

Если класс iParentChild не определяет __construct, то он наследует один от его суперкласса, iParent. Если он задал __construct, то это переопределит конструктор родителя и, следовательно, как указано в вашем вопросе, нужно будет позвонить parent::__construct().

EDIT

Обратите внимание, что даже если iParentChild делает переопределения __construct без вызова родительского конструктора не будет ошибкой в ​​этом примере. Это связано с тем, что php обеспечивает инициализацию переменных по умолчанию в контексте, в котором они используются, и здесь они используются как строки. На практике это лучше не полагаться на это:

From the PHP Manual - Basics:

Не нужно инициализировать переменные в PHP, однако это очень хорошая практика. Неинициализированные переменные имеют значение по умолчанию их тип в зависимости от контекста, в котором они используются - booleans по умолчанию FALSE, целые числа и поплавки по умолчанию равны нулю, строки (например, , используемые в эхо) задаются как пустая строка, а массивы становятся до пустого массива .

Опираясь на значение по умолчанию неинициализированной переменной, является проблематичным при включении одного файла в другой, который использует то же имя переменной. Это также серьезный риск для безопасности при включении register_globals. Ошибка уровня E_NOTICE выдается в случае , работающей с неинициализированными переменными, однако не в случае добавляющих элементов к неинициализированному массиву. isset() язык Конструкция может использоваться для определения, была ли переменная уже выполнена .

Попытка вызова метода на неинициализированный объект-член привела бы к ошибке.

+0

См. Обновленную версию. Я добавил __construct в iParentChild, но у меня нет ошибок. – dofenco

+0

Я скопировал ваш код и вывод, который я получил, как и ожидалось: конструктор IParentChildDevice Browser – redbirdo

+0

Да, но теперь у меня есть конструктор в iParentChild. Я ожидал получить ошибку, когда this-> getDetails() выполняется, поскольку родительский конструктор не инициализирован. – dofenco