2010-01-03 102 views
7

如果我有一個由許多其他類擴展的父類,並且我想確保父類的構造函數總是運行,那麼聲明構造函數final是個壞主意?在PHP中聲明類的ctor'final'是否是不好的做法?

我的想法做這樣的:

class ParentClass { 

    public final function __construct() { 

     //parent class initialization... 

     $this->construct(); 

    } 

    protected function init() { 

     echo 'constructing<br>'; 

    } 

} 

class ChildClass extends ParentClass { 

    protected function init() { 

     //child class initialization 

     echo 'constructing child<br>'; 

    } 

} 

這樣子類可以有一個排序的構造函數,父類的構造函數都會被執行。這是不好的做法嗎?

+0

我明白你爲什麼不信任PHP程序員申報ClassName()構造函數,但我不明白爲什麼你關心:-) – 2010-01-03 03:28:41

+0

我只是想要明確我的代碼 – 2010-01-03 10:56:02

回答

9

聲明一個final__construct確保沒有人擴展你的類可以實現一個同名的方法。從表面上看,這似乎意味着沒有其他人可以爲這個類的子類聲明一個構造函數,但這不是事實,因爲PHP 4風格的ClassName()仍然可以很好地作爲構造函數。所以真的,聲明一個構造函數爲最終在PHP中沒有任何東西。

+0

這是真的,我沒有考慮到這一點。父類的__construct方法仍然會被調用嗎?或者不同名稱的子類的構造函數是否會覆蓋它? – 2010-01-03 10:55:28

+1

父構造函數永遠不會自動調用。您仍然必須在子類構造函數中調用'parent :: __ construct()'或'parent :: ClassName()'。 – Mike 2010-01-03 17:01:20

-1

完成構造函數之後,不能將任何變量傳遞給初始化函數。它強制你的類的用戶使用全局變量作爲其子類的設置。

在Zend框架中使用可重寫的init()是很常見的做法,但我從來沒有見過在此處定義構造函數。

+0

真的嗎?我只是試過了,我可以將一個變量從finalized構造函數傳遞給子初始化函數並回顯它 – 2010-01-03 01:32:22

+1

哦,我的意思是,用戶不能通過任何未知的參數 – 2010-01-03 02:48:09

+0

但是,ZF正在轉移到傳遞配置對象作爲一種手段標準化參數如何在對象之間傳遞。 – 2010-01-03 03:09:34

3

由於PHP 5.3.3,我有5.6和7.0測試此,聲明類final__construct方法將防止任何兒童類中重寫或者使用__constructClassName()的PHP 4的風格構造(注意,自PHP 7起,PHP 4風格已棄用)。防止聲明構造函數的子類將確保始終調用父構造函數。這當然不會允許任何子類實現自己的構造函數邏輯。雖然我不會推薦它作爲一般的良好實踐,但肯定會有實際用例。

一些例子:

不宣__construct最終

class ParentClassWithoutFinal { 
    private $value = "default"; 

    public function __construct() { 
     $this->value = static::class; 
    } 

    function __toString() { 
     return $this->value; 
    } 
} 

class ChildClassA extends ParentClassWithoutFinal { 
    public function __construct() { 
     // Missing parent::__construct(); 
    } 
} 

echo (new ChildClassA()); // ouput: default 

隨着最後__construct

class ParentClassWithFinal extends ParentClassWithoutFinal { 
    public final function __construct() { 
     parent::__construct(); 
    } 
} 

class ChildClassB extends ParentClassWithFinal { 
} 

echo (new ChildClassB()); // output: ChildClassB 

試圖在一個子類來聲明__construct

class ChildClassC extends ParentClassWithFinal { 
    public function __construct() { 
    } 
} 

// Fatal error: Cannot override final method ParentClassWithFinal::__construct() 

試圖在一個子類

class ChildClassD extends ParentClassWithFinal { 
    public function ChildClassD() { 
    } 
} 

// Fatal error: Cannot override final ParentClassWithFinal::__construct() with ChildClassD::ChildClassD() 
// Also in PHP 7: Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; ChildClassD has a deprecated constructor 
相關問題