先上段代码:

class B {
function __construct(){
echo "call: B.construct\n";
}

public function display() {
echo "in display:\n";
$this->__construct();
}
}

class A extends B {
private $_c;

function __construct(){
echo "call: A.construct\n";
parent::__construct();

}
}

$a = new A();
echo "<pre>";
$a->display();
echo "</pre>";



这段代码会显示什么呢?

下面是结果:

call: A.construct call: B.construct
in display:
call: A.construct
call: B.construct

 

很奇怪,居然在父类里调用$this->_construct成了调用子类的$this->_construct方法....

晕,php对象编程实在是实现得有点让人费解,期待其改进啊..

 

而在人人的php-sdk里面就有这么一个问题,困扰了我大半天...

SDK里面有两个类,HttpRequestService和RenrenRestApiService,后者继承自前者。

因为我对RenrenRestApiService这个类对config的初始化的方法有点不爽(它是用全局变量的形式传入参数的,我觉得应该是通过construct构造方法传),于是我修改了构造方法。但是,一直报错,$this->_config为空,我输出$this->_config发现其居然有两次输出,construct方法只有被调用一次啊,我以为是我构造对象的时候那个地方错误的使用了默认的构造方法,往前检查均没发现问题。

后来,我仔细的trace我的代码,才在HttpRequestService类的call方法里面发现了这么一行:

is_object($this->ch) or $this->__construct();

这里construct方法里面执行了对$this->ch句柄的初始化过程,不知道原作者出于什么考虑加上这行,但是,事实上,我测试发现,还真有可能$this->ch没有被初始化,也就是说执行了or后面的方法。


但是,尽管如此,我觉得这里直接调用类的构造方法还是不合适的。如果想要初始化ch句柄,就应该把构造的过程写成一个函数,然后调用这个函数(在construct方法和这里),而不是把构造过程写在构造函数里,而在这里调用构造函数。

 

所以最终给出我的解决方案,

新建一个init_ch方法,把原有的construct中对ch句柄的初始化过程放在这个方法内,然后在construct和这里调用init_ch方法。

如下:

    public function __construct(){

$this->init_ch();
}

private function init_ch() {
// do something to init ch
......
}



// in method call
......

//is_object($this->ch) or $this->__construct();
//bug!!!

is_object($this->ch) or $this->init_ch();

......



posted on 2012-04-01 14:31  龍之心  阅读(248)  评论(0)    收藏  举报