<转>__construct()和__initialize()

ThinkPHP中的__initialize()和类的构造函数__construct()
网上有很多关于__initialize()的说法和用法,总感觉不对头,所以自己测试了一下。将结果和大家分享。不对请更正。
首先,我要说的是
1、__initialize()不是php类中的函数,php类的构造函数只有__construct().
2、类的初始化:子类如果有自己的构造函数(__construct()),则调用自己的进行初始化,如果没有,则调用父类的构造函数进行自己的初始化。
3、当子类和父类都有__construct()函数的时候,如果要在初始化子类的时候同时调用父类的__constrcut(),则可以在子类中使用parent::__construct().
如果我们写两个类,如下

  1. class Action{
  2.     public function __construct()
  3.     {
  4.         echo 'hello Action';
  5.     }
  6. }

  7. class IndexAction extends Action{
  8.     public function __construct()
  9.     {
  10.         echo 'hello IndexAction';
  11.     }
  12. }

  13. $test = new IndexAction;
  14. //output --- hello IndexAction
复制代码

很明显初始化子类IndexAction的时候会调用自己的构造器,所以输出是'hello IndexAction'。
但是将子类修改为

  1. class IndexAction extends Action{
  2.     public function __initialize()
  3.     {
  4.         echo 'hello IndexAction';
  5.     }
  6. }
复制代码

那么输出的是'hello Action'。因为子类IndexAction没有自己的构造器。
如果我想在初始化子类的时候,同时调用父类的构造器呢?

  1. class IndexAction extends Action{
  2.     public function __construct()
  3.     {
  4.         parent::__construct();
  5.         echo 'hello IndexAction';
  6.     }
  7. }
复制代码

这样就可以将两句话同时输出。
当然还有一种办法就是在父类中调用子类的方法。

  1. class Action{
  2.     public function __construct()
  3.     {
  4.         if(method_exists($this,'hello'))
  5.         {
  6.             $this -> hello();
  7.         }
  8.         echo 'hello Action';
  9.     }
  10. }

  11. class IndexAction extends Action{
  12.     public function hello()
  13.     {
  14.         echo 'hello IndexAction';
  15.     }
  16. }
复制代码

这样也可以将两句话同时输出。
而,这里子类中的方法hello()就类似于ThinkPHP中__initialize()。
所以,ThinkPHP中的__initialize()的出现只是方便程序员在写子类的时候避免频繁的使用 parent::__construct(),同时正确的调用框架内父类的构造器,所以,我们在ThnikPHP中初始化子类的时候要用 __initialize(),而不用__construct(),当然你也可以通过修改框架将__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构造函数仅仅在创建对象的时候调用一次,跟其它方法调用没有关系。

posted on 2015-11-22 13:19  hahahahahai12  阅读(176)  评论(0)    收藏  举报

导航