2010-01-03 3 views
7

Wenn ich eine Elternklasse habe, die um viele weitere Klassen erweitert wurde, und ich möchte sicherstellen, dass der Konstruktor der Elternklasse IMMER ausgeführt wird, ist es eine schlechte Idee, den Konstruktor final zu deklarieren?Ist es in der Praxis eine schlechte Sache, in PHP den Abschluss einer Klasse als "final" zu deklarieren?

Ich dachte an so etwas wie dies zu tun:

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>'; 

    } 

} 

auf diese Weise das Kind Klasse eine Art-of-Konstruktor haben kann, und die Konstruktor der übergeordneten Klasse wird immer ausgeführt werden. Ist das eine schlechte Übung?

+0

Ich verstehe, warum Sie nicht vertrauen PHP-Programmierer, aber ich verstehe nicht, warum Sie kümmern versucht, ich bin gerade :-) –

+0

zu erklären explizit mit meinem Code sein –

Antwort

9

Das Deklarieren eines final__construct stellt sicher, dass niemand, der Ihre Klasse erweitert, eine Methode mit demselben Namen implementieren kann. Auf der Oberfläche scheint dies zu bedeuten, dass niemand sonst einen Konstruktor für Unterklassen dieser Klasse deklarieren könnte, aber das ist nicht wahr, da der PHP 4-Stil von ClassName() immer noch gut als alternativer Name für funktioniert der Konstruktor. Wenn Sie einen Konstruktor als final deklarieren, erhalten Sie in PHP nichts.

+0

finalisieren möchte, das ist wahr, ich hatte das nicht berücksichtigt.Wird die '__construct' Methode der Elternklasse trotzdem aufgerufen? Oder würde der Konstruktor der Kindklasse mit einem anderen Namen ihn einfach überschreiben? –

+1

Übergeordnete Konstruktoren werden niemals automatisch aufgerufen. Sie müssten im Konstruktor der untergeordneten Klasse immer noch "parent :: __ construct()" oder "parent :: ClassName()" aufrufen. – Mike

-1

Nach Abschluss des Konstruktors können Sie keine Variablen an die Initialisierungsfunktion übergeben. Er zwingt Benutzer Ihrer Klasse dazu, Globals als Einstellungen für ihre untergeordneten Klassen zu verwenden.

In Zend Framework die Verwendung von overridable init() ist gängige Praxis, aber ich habe nie gesehen, einen Konstruktor dort finalisieren.

+0

Wirklich? Ich habe es gerade ausprobiert und ich könnte eine Variable aus dem endgültigen Konstruktor an die Child-Initialisierungsfunktion übergeben und es echo –

+1

Oh, ich meine, Benutzer kann keine unvorhergesehenen Parameter übergeben –

+0

Allerdings bewegt sich ZF auf die Weitergabe von Config-Objekten als Mittel Standardisieren, wie Parameter zwischen Objekten übergeben werden. –

3

Ab PHP 5.3.3, ich habe diese getestet mit 5,6 und 7,0, die __construct Methode einer Klasse deklarieren final entweder den Konstruktor überschreiben jedes Kind Klasse verhindern mit __construct oder die PHP-4-Stil ClassName() (beachten Sie, dass die PHP 4 Stil ist ab PHP 7 veraltet. Durch das Verhindern, dass eine untergeordnete Klasse einen Konstruktor deklariert, wird sichergestellt, dass der übergeordnete Konstruktor immer aufgerufen wird. Dies wird natürlich keiner untergeordneten Klasse erlauben, ihre eigene Konstruktorlogik zu implementieren. Es würde sicherlich praktische Anwendungsfälle geben, obwohl ich es generell nicht empfehlen würde.

Einige Beispiele:

Ohne __construct final

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 

Mit final __construct

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

class ChildClassB extends ParentClassWithFinal { 
} 

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

Versuch __construct in einer untergeordneten Klasse zu erklären

erklärt 210
class ChildClassC extends ParentClassWithFinal { 
    public function __construct() { 
    } 
} 

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

Versuch ClassName() Konstruktor in einer Kindklasse

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 
Verwandte Themen