2010-11-08 33 views
8

我正在學習PHP,當我試圖弄清楚爲什麼構造函數沒有被調用時,發現了一些令人驚訝的行爲。我可以強制子類使用父類的構造函數嗎?

<?php 
    class Shape { 

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

    class Triangle extends Shape { 

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

    $tri = new Triangle(); 
?> 

我習慣java,所以我認爲這會輸出「形狀。三角形」。令人驚訝的是,它只是輸出「三角形」。我搜索了這個問題,顯然我可以通過將parent::__construct();加入孩子班來解決它,但這看起來並不理想。有什麼我可以做的Shape類,以確保子類總是調用父構造函數?當父母有一個構造函數時,我真的必須在每個孩子的類中寫parent::__construct();嗎?

+1

我很確定你必須,除非你不定義子構造函數。 – 2010-11-08 03:47:58

+0

[Superclass的構造函數在PHP中的子構造函數中運行嗎?]的可能的重複(http://stackoverflow.com/questions/738571/is-superclasss-constructor-run-inside-child-constructor-in-php) – outis 2012-02-24 09:28:39

回答

10

如果您在子類中定義了一個名稱相同的方法,則父類的方法將被覆蓋,並且在任何情況下都不會被調用,除非明確這樣做。 I.e .:沒有,你無能爲力,你必須明確地致電parent::__constructor()

+0

+1沒有別的補充。 – Hamish 2010-11-08 03:59:19

+1

您也可以讓父類聲明父構造函數調用的抽象或空初始化方法。 – erisco 2010-11-08 05:21:32

+0

@erisco這將是一個很好的設計模式來解決這個問題,但它不會改變事實。 :) – deceze 2010-11-08 05:43:49

2

根據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的,則可以使用final keyword防止父方法被覆蓋。

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

你可以結合使用與預先定義init()方法,以確保您的父類的構造被調用。

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

這將輸出

TriangleShape. 

,如果你記錄了init()方法做什麼,以及它被稱爲父最好是隻使用這樣的設計。

相關問題