2014-01-24 82 views
0

是否有可能從基類構造函數調用擴展類方法?從基類構造函數的擴展類調用方法

這裏是我想要做的一個例子:

<?php 
class SomeController extends Controller { 
    public function init() { 
     echo "lol"; 
    } 
} 

class Controller { 
    public function __construct() { 
     // do something to call init() in SomeController. 
    } 
} 

只是想知道是這樣的可能。

回答

1

除了作爲超類的子類強加在子類上的約束外,超類無法知道關於它們自己的子類的任何內容。如果你仔細考慮一下,那就很有道理。他們怎麼可能?畢竟,開發者可以添加任何他們想要的子類。

然而,超類可以做什麼是強制其子類具有哪些方法。如果方法存在於超類中,則它必須存在於子類中,因爲您無法刪除子類中的方法。如果你使用一個具體的超類作爲你的基類,那麼你只需要實現一個在超類中什麼都不做的方法,並且所有的子類都會擁有它。對於需要在該方法中發生的任何子類,它們可以用它們自己的實現來覆蓋它。你可以從超類調用該方法,並確保該子類具有它的實現。

爲此,該方法不能是私人的。它必須得到保護或公開。

class Controller { 

    protected function init() { 
     // Do nothing, this method exists only to be overridden 
    } 

    public function __construct() { 
     // do something to call init() in SomeController. 
     $this -> init(); 
    } 
} 

如果它沒有意義在自己的存在的超正確的,那麼你可以讓超初始化一個抽象方法,所以你不必提供一個實現的。您只能在抽象類中聲明抽象方法,而抽象類不能實例化。

從超類繼承的任何子類現在將被迫實現一個init()方法。如果沒有,那麼當您嘗試運行您的代碼時會發生致命錯誤。

abstract class Controller { 

    abstract protected function init(); 

    public function __construct() { 
     // do something to call init() in SomeController. 
     $this -> init(); 
    } 
} 

正如在前面的例子中,這確保了此一個的子類有一個init()方法,它是安全的,因此調用的init()從超。

注意:由於PHP的Zend Engine的實現方式的特殊性,當超類不知道子類方法時,理論上可以從超類調用子類方法。然而,這不是一個蓄意的設計決定,而是沒有證據的行爲。因此可以在任何時候刪除它。即使PHP永遠保持這種狀態,從超類調用子類方法仍然是一個非常糟糕的做法,但不確定子類是否實現了該方法。永遠不要依賴那種行爲。