2010-11-08 9 views
8

Uczę się PHP i znalazłem zaskakujące zachowanie, gdy próbowałem dowiedzieć się, dlaczego konstruktor nie został wywołany.Czy mogę zmusić klasę podrzędną do korzystania z konstruktora nadrzędnego?

<?php 
    class Shape { 

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

    class Triangle extends Shape { 

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

    $tri = new Triangle(); 
?> 

Jestem przyzwyczajony do java, więc pomyślałem, że to wypisze "Kształt. Trójkąt". Zaskakująco, po prostu wychodzi "Trójkąt". Szukałem problemu i najwyraźniej mogę go trochę poprawić, umieszczając parent::__construct(); w klasie potomnej, ale to nie wydaje się idealne. Czy jest coś, co mogę zrobić dla klasy Shape, aby upewnić się, że klasy potomne zawsze wywołują konstruktor macierzysty? Czy naprawdę muszę pisać parent::__construct(); w klasie każdego dziecka, gdy rodzic ma konstruktora?

+1

Jestem prawie pewien, że musisz, chyba że nie zdefiniujesz konstruktora potomnego. –

+0

możliwy duplikat konstruktora [Czy Superklass działa wewnątrz konstruktora potomnego w PHP?] (Http://stackoverflow.com/questions/738571/is-superclasss-constructor-run-inside-child-constructor-in-php) – outis

Odpowiedz

10

Jeśli zdefiniujesz metodę o tej samej nazwie w klasie potomnej, metoda rodzica zostanie nadpisana i nie będzie wywoływana w żadnych okolicznościach, chyba że zrobisz to jawnie. Np .: Nie, nie możesz nic zrobić, musisz zadzwonić pod numer parent::__constructor().

+0

+1 nic więcej do dodania. – Hamish

+1

Można również zadeklarować rodzic jako abstrakcyjną lub pustą metodę inicjowania wywoływaną przez macierzysty konstruktor. – erisco

+0

@erisco To byłby dobry wzór do obejścia tego, ale nie zmienia faktów. :) – deceze

2

Zgodnie z podręcznikiem 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

W PHP 5 można użyć final keyword zapobiec metody nadrzędnej przed nadpisane.

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

Można to wykorzystać w połączeniu z wcześniej zdefiniowanym init() metody, aby zapewnić konstruktor rodzic został powołany.

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

To byłoby wyjście

TriangleShape. 

Wskazane jest, aby używać tylko projekt takiego jeśli udokumentować co robi metoda init() i gdzie to się nazywa w rodzica.

Powiązane problemy