一、PHP中只有__construct方法爲構造方法,會自動執行,_initialize方法自己不是構造方法,不會自動執行,只是在thinkphp的Controller.class.php中咱們能夠看到以下代碼php
public function __construct() { Hook::listen('action_begin',$this->config); //實例化視圖類 $this->view = Think::instance('Think\View'); //控制器初始化 if(method_exists($this,'_initialize')) $this->_initialize(); }
核心就在於method_exists這一段,典型的父類調用子類的一個方法。所以咱們在有控制器繼承Controller.class.php的時候,例如BaseController.class.php定義了_initialize方法,則會在初始化BaseController這個類的時候自動去調用_initialize方法。thinkphp
二、咱們常常會看到不少代碼繼承關係比較複雜,例如ide
a、ProjectController.class.php函數
class ProjectController extends UcenterBaseController{ protected function _initialize(){ $this->model = new ProjectModel(); parent::_initialize(); }
b、UcenterBaseController.class.phpthis
class UcenterBaseController extends FrontendBaseController{ protected function _initialize(){ decide_terminal(); $this->tablePrefix = C('DB_PREFIX'); parent::_initialize();
c、FrontendBaseController.class.php指針
class FrontendBaseController extends BaseController { /** * 初始化入口 */ protected function _initialize() { parent::_initialize(); if(APP_NAME == 'study') { set_theme(C('STUDY_THEME')); } else { set_theme(C('SITE_INFO.templet')); } }
d、BaseController.class.phpcode
class BaseController extends Controller { /** * 初始化入口 */ protected function _initialize() { decide_terminal(); decide_site();
可能你們在碰到這種繼承關係的時候比較暈,多重繼承究竟執行的是哪一個_initialize方法,這個你們都須要注意php的第二個特性,若是父子類均有_initialize()函數,則子類覆蓋了父類的,若是子類沒有而父類有,則子類繼承父類的。在調用子類對象的_initialize()時,不會致使自動調用父類的_initialize(),咱們必須顯示的用parent::_initialize()來調用父類的方法。也就是說程序在初始化Project.class.php方法的時候,發現這個類有了_initialize方法,則不會自動去執行父類UcenterBaseController的,直接執行本身定義的的_initialize,而後_initialize中有parent::_initialize()再去執行UcenterBaseController的_initialize方法,這個裏面再調用parent::_initialize執行。須要注意的一點是:在BaseController.class.php中不要寫parent::_initialize,會直接報錯的,由於Controller.class.php中沒有_initialize方法對象
三、總結繼承
(1)_initialize()函數是在任何方法執行以前,都要執行的,固然也包括_ _construct構造函數,注意,_ _construct這裏是雙劃線,而_initialize()函數是單劃線。
(2)若是父子類均有_initialize()函數,則子類覆蓋了父類的,若是子類沒有而父類有,則子類繼承父類的。在調用子類對象的_initialize()時,不會致使自動調用父類的_initialize()。
(3)默認狀況下,子類的構造函數也不會自動調用父類的構造函數,這一點與Java不一樣。實際編寫子類的構造函數時,通常都要加上父類構造函數的主動調用 parent::_ _construct(),不然會致使子類對象空指針的異常,如Call to a member function assign() on a non-object。
(4)_initialize()函數是在「任何」方法調用以前都要調用的,也就是說若是存在_initialize()函數,調用對象的任何方法都會導 致_initialize()函數的自動調用,而_ _construct構造函數僅僅在建立對象的時候調用一次,跟其它方法調用沒有關係。ci