2016-01-11 4 views
4

Например, в структуре Yii2 класс yii\filters\AccessControl переопределяет функцию init() из своего родительского класса yii\base\Object. Этот класс объектов, в свою очередь метод-конструктор так:Почему у некоторых php-классов есть пустой метод init()?

Class Object implements Configurable { 
     public function __construct($config = []) 
     { 
      if (!empty($config)) { 
       Yii::configure($this, $config); 
     } 
     $this->init(); // calls the method defined below 
     } 
    } 
// and the definition of this init function ... 
    public function init() 
    { 
    } 

Теперь нет никакого очевидного использования написания такой пустой функции, если никто не хочет использовать для инициализации некоторых свойств он/она может понадобиться в будущем.

Но тогда метод __construct() имеет то же самое использование! Мне нужно понять, как этот метод init() полезен.

ответ

5

Причина проста: они ожидают, чтобы вы расширить класс

Так что вы могли бы сделать что-то вроде этого

class Bob extends Object { 
    public function init() { 
     $this->setup_something(); 
    } 
} 

Итак, поскольку Bob расширяет Object метод из Bob является тот, который вызывается. Если вам не нужно инициализировать что-то, просто пропустите defintion, и базовый класс вызовет пустой метод.

Это удерживает вас от того, чтобы сделать что-то потенциально хаотичным: перезаписать конструктор

class Bob extends Object { 
    public function __construct($config = []) { 
     $this->setup_something(); 
    } 
} 

Теперь, это грязно, потому что есть что-то критическое много людей пропустить (и я преднамеренно не для этого примера): родительский конструктор не будет называться (вы можете сделать это, имея parent::__construct($config)). Таким образом, имея отдельный init(), вы избегаете этого беспорядка полностью. Существует явный метод для вашей собственной настройки.

3

Обсуждалось at length на форумах Yii. Вот проект проекта Yii:

Одна из причин для init() - это жизненные циклы объекта (или, если быть точнее, компонента).

С помощью метода init() можно сконфигурировать объект после его создания, пока он не будет полностью инициализирован. Например, компонент приложения можно настроить с помощью конфигурации приложения. Если вы переопределите его метод init(), вы будете уверены, что эта настройка применяется, и вы можете безопасно проверить, все ли готово. Подобное происходит с виджетами и другими настраиваемыми компонентами.

Даже если init() вызывается внутри конструктора, а не другим объектом, он имеет смысл. Например, в CApplication есть preInit() и init(). Они устанавливают жизненные циклы приложения и могут быть переопределены, так что настройка выполняется только в ожидаемых жизненных циклах.

Я согласен с вами в том, что наименование метода очень важно. Здесь, в Yii, метод init() означает, что объект уже полностью настроен, и в этом методе необходимо выполнить некоторую дополнительную работу по инициализации.

и:

Каждая функция должна существовать по причине. В случае Yii метод init() в основном предлагается для настройки в определенный жизненный цикл компонента. В приложении календаря вам может потребоваться или не понадобиться init(). Если вы намерены опубликовать его для публичного использования, я бы предложил вам быть более консервативным, чтобы разрешить настройку. То есть, не определяйте init(), если у вас нет веских оснований для этого. Когда вы предоставляете защищенный или открытый метод, это означает, что вам нужно поддерживать его в будущих выпусках.

Смежные вопросы