2010-11-08 2 views
8

J'apprends PHP et j'ai trouvé un comportement surprenant quand j'essayais de comprendre pourquoi un constructeur n'était pas appelé. Je suis habitué à Java, donc je pensais que cela produirait "Shape, Triangle." Étonnamment, il sort juste "Triangle". J'ai cherché le problème et apparemment je peux un peu le résoudre en mettant parent::__construct(); dans la classe enfant, mais cela ne semble pas idéal. Est-ce que je peux faire quelque chose à la classe Shape pour m'assurer que les classes enfant appellent toujours le constructeur parent? Dois-je vraiment écrire parent::__construct(); dans la classe de chaque enfant chaque fois que le parent a un constructeur?Puis-je forcer une classe enfant à utiliser le constructeur du parent?

+1

Je suis assez sûr qu'il le faut, sauf si vous ne définissez pas le constructeur enfant. –

+0

duplication possible de [Le constructeur de Superclass s'exécute-t-il dans le constructeur enfant en PHP?] (Http://stackoverflow.com/questions/738571/is-superclasss-constructor-run-inside-child-constructor-in-php) – outis

Répondre

10

Si vous définissez une méthode du même nom dans une classe enfant, la méthode du parent est substituée et ne sera en aucun cas appelée, à moins que vous ne le fassiez explicitement. I.e .: Non, il n'y a rien que vous puissiez faire à ce sujet, vous devez appeler parent::__constructor() explicitement.

+0

+1 rien d'autre à ajouter. – Hamish

+1

Vous pouvez également demander au parent de déclarer une méthode d'initialisation abstraite ou vide que le constructeur parent appelle. – erisco

+0

@erisco Ce serait un bon modèle de conception pour contourner cela, mais cela ne change rien aux faits. :) – deceze

2

Selon le manuel PHP:

Parent constructors are not called implicitly if the child class defines 
a constructor. In order to run a parent constructor, a call to 
parent::__construct() within the child constructor is required. 
8

PHP 5, vous pouvez utiliser la final keyword pour empêcher une méthode mère d'être substituée.

<?php 
class BaseClass { 
    public function test() { 
     echo "BaseClass::test() called\n"; 
    } 

    final public function moreTesting() { 
     echo "BaseClass::moreTesting() called\n"; 
    } 
} 

class ChildClass extends BaseClass { 
    public function moreTesting() { 
     echo "ChildClass::moreTesting() called\n"; 
    } 
} 
// Results in Fatal error: Cannot override final method BaseClass::moreTesting() 

Vous pouvez utiliser cette en combinaison avec une méthode init() prédéfini pour assurer votre constructeur parent a été appelé.

<?php 
abstract class Shape { 

    final function __construct() { 
     $this->init(); 
     echo 'Shape.'; 
    } 

    abstract public function init(); 
} 

class Triangle extends Shape { 

    function init() {   
     echo 'Triangle'; 
    } 
} 

$tri = new Triangle(); 

Cette génèrerait

TriangleShape. 

Il est conseillé d'utiliser seulement un design comme celui-ci si vous documentez ce que la méthode init() fait, et où il est appelé dans le parent.

Questions connexes