2010-01-03 4 views
7

Если у меня есть родительский класс, который расширен множеством и множеством других классов, и я хочу, чтобы конструктор родительского класса ВСЕГДА выполнялся, это плохая идея объявить конструктор final?Является ли плохая практика объявлением класса «final» класса в PHP?

Я думал сделать что-то вроде этого:

class ParentClass { 

    public final function __construct() { 

     //parent class initialization... 

     $this->construct(); 

    } 

    protected function init() { 

     echo 'constructing<br>'; 

    } 

} 

class ChildClass extends ParentClass { 

    protected function init() { 

     //child class initialization 

     echo 'constructing child<br>'; 

    } 

} 

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

+0

Я понимаю, почему вы не доверяете PHP программистов, но я не понимаю, почему вы все равно :-) –

+0

Я просто пытаюсь быть явным с моим кодом –

ответ

9

Объявление final__construct гарантирует, что никто, кто расширяет ваш класс, не может реализовать метод с тем же именем. На первый взгляд это, похоже, означало бы, что никто не может объявить конструктор для подклассов этого класса, но это не так, поскольку стиль PHP 4 ClassName() по-прежнему отлично работает в качестве альтернативного имени для конструктор. Так что, объявляя конструктор как final, вы ничего не получаете в PHP.

+0

, это правда, я не думал об этом.До сих пор был вызван метод родительского класса '__construct'? Или конструктор дочернего класса другого имени просто переопределяет его? –

+1

Родительские конструкторы никогда не вызываются автоматически. Вам все равно придется вызывать 'parent :: __ construct()' или 'parent :: ClassName()' в конструкторе дочернего класса. – Mike

-1

После завершения построения конструктора вы не можете передавать какие-либо переменные в функцию инициализации. Это заставляет пользователей вашего класса использовать глобальные переменные в качестве настроек для своих дочерних классов.

В Zend Framework, использующем overridable init(), является обычной практикой, но я никогда не видел завершения работы над конструктором.

+0

Действительно? Я просто попробовал это, и я мог передать переменную из завершенного конструктора в функцию инициализации ребенка и выполнить эхо-код –

+1

. О, я имею в виду, что пользователь не может передать какой-либо непредвиденный параметр –

+0

Однако ZF переходит к обходу объектов конфигурации как средство стандартизации, как параметры передаются между объектами. –

3

В РНР 5.3.3, я испытал это с 5.6 и 7.0, объявляя __construct метод класса final предотвратит дочерний класс перекрывая конструктор либо с помощью __construct или стиль PHP 4 из ClassName() (заметим, что PHP 4 стиль устарел с PHP 7). Предотвращение дочернего класса, объявляющего конструктор, гарантирует, что родительский конструктор всегда вызывается. Это, конечно же, не позволит дочерним классам реализовать свою собственную конструкторскую логику. Для этого наверняка будут практические примеры использования, хотя я бы не рекомендовал его в качестве хорошей практики в целом.

Некоторые примеры:

без объявления __construct окончательного

class ParentClassWithoutFinal { 
    private $value = "default"; 

    public function __construct() { 
     $this->value = static::class; 
    } 

    function __toString() { 
     return $this->value; 
    } 
} 

class ChildClassA extends ParentClassWithoutFinal { 
    public function __construct() { 
     // Missing parent::__construct(); 
    } 
} 

echo (new ChildClassA()); // ouput: default 

С окончательной __construct

class ParentClassWithFinal extends ParentClassWithoutFinal { 
    public final function __construct() { 
     parent::__construct(); 
    } 
} 

class ChildClassB extends ParentClassWithFinal { 
} 

echo (new ChildClassB()); // output: ChildClassB 

Попытка объявить __construct в дочернем классе

class ChildClassC extends ParentClassWithFinal { 
    public function __construct() { 
    } 
} 

// Fatal error: Cannot override final method ParentClassWithFinal::__construct() 

Попытка объявить ClassName() конструктор в классе ребенка

class ChildClassD extends ParentClassWithFinal { 
    public function ChildClassD() { 
    } 
} 

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD() 
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor 
Смежные вопросы