2010-11-08 8 views
8

Sto imparando PHP e trovato alcuni comportamenti sorprendente quando stavo cercando di capire perché un costruttore non è stato sempre chiamato.Posso forzare una classe figlia a utilizzare il costruttore genitore?

<?php 
    class Shape { 

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

    class Triangle extends Shape { 

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

    $tri = new Triangle(); 
?> 

Sono abituato a java, quindi ho pensato che avrebbe prodotto "Shape. Triangle". Sorprendentemente, emette solo "Triangolo". Ho cercato per il problema ea quanto pare posso genere di sorta risolvere il problema mettendo parent::__construct(); nella classe bambino, ma che non sembra l'ideale. C'è qualcosa che posso fare alla classe Shape per assicurarmi che le classi figlio chiamino sempre il costruttore genitore? Devo davvero scrivere parent::__construct(); nella classe di ogni bambino ogni volta che il genitore ha un costruttore?

+1

Sono abbastanza sicuro che si deve, a meno che non si definisce il costruttore bambino. –

+0

possibile duplicato del [è il costruttore della superclasse eseguito all'interno costruttore bambino in PHP?] (Http://stackoverflow.com/questions/738571/is-superclasss-constructor-run-inside-child-constructor-in-php) – outis

risposta

10

Se si definisce un metodo con lo stesso nome in una classe figlia, il metodo del genitore viene ignorata e non saranno chiamati in nessun caso, a meno che non lo si fa in modo esplicito. I.e: No, non c'è niente che tu possa fare al riguardo, devi chiamare lo parent::__constructor() esplicitamente.

+0

+1 nient'altro da aggiungere. – Hamish

+1

Si potrebbe anche chiedere al genitore di dichiarare un metodo di inizializzazione astratto o vuoto che chiama il costruttore genitore. – erisco

+0

@erisco Questo sarebbe un buon modello di progettazione per aggirare questo, ma non cambia i fatti. :) – deceze

2

Secondo il manuale di 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

Dal PHP 5, è possibile utilizzare il final keyword per evitare che un metodo genitore venga sovrascritto.

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

È possibile utilizzare questo in combinazione con un metodo predefinito init() per garantire la vostra costruttore genitore è stato chiamato.

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

Questo sarebbe uscita

TriangleShape. 

E 'consigliabile utilizzare solo un progetto come questo se si documentare ciò che il metodo init() fa, e dove è chiamato nel genitore.

Problemi correlati