2010-11-08 8 views
8

Estoy aprendiendo PHP y encontré un comportamiento sorprendente cuando estaba tratando de descubrir por qué no se llamaba a un constructor.¿Puedo forzar a una clase secundaria a usar el constructor padre?

<?php 
    class Shape { 

     function __construct() { 
      echo 'Shape.'; 
     } 
    } 

    class Triangle extends Shape { 

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

    $tri = new Triangle(); 
?> 

I'm a java, así que pensé que esto daría como resultado "Shape. Triangle". Sorprendentemente, solo muestra "Triangle". Busqué el problema y aparentemente puedo arreglarlo poniendo parent::__construct(); en la clase secundaria, pero eso no parece ideal. ¿Hay algo que pueda hacer en la clase Shape para garantizar que las clases secundarias siempre llamen al constructor padre? ¿Realmente tengo que escribir parent::__construct(); en la clase de cada niño cuando el padre tiene un constructor?

+1

Estoy bastante seguro de que tiene que hacerlo, a menos que no defina el constructor hijo. –

+0

posible duplicado de [¿El constructor de Superclass se ejecuta dentro del constructor hijo en PHP?] (Http://stackoverflow.com/questions/738571/is-superclasss-constructor-run-inside-child-constructor-in-php) – outis

Respuesta

10

Si define un método del mismo nombre en una clase secundaria, el método del padre se reemplaza y no se llamará bajo ninguna circunstancia, a menos que lo haga explícitamente. Es decir .: No, no hay nada que puedas hacer al respecto, debes llamar al parent::__constructor() de manera explícita.

+0

+1 nada más para agregar. – Hamish

+1

También podría hacer que el padre declare un método de inicialización abstracto o vacío que llame el constructor principal. – erisco

+0

@erisco Ese sería un buen patrón de diseño para evitar esto, pero no cambia los hechos. :) – deceze

2

De acuerdo con el manual de 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

A partir de PHP 5, se puede utilizar el final keyword para prevenir un método padres que se cambie.

<?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() 

Usted podría utilizar esto en combinación con un init() método predefinido para asegurar que su constructor padre se llamaba.

<?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(); 

Esto haría salida

TriangleShape. 

Es aconsejable utilizar sólo un diseño como este si documentar lo que hace el método init(), y donde se le llama en la matriz.

Cuestiones relacionadas