class foo { private function m() { echo 'foo->m() '; } public function call() { $this->m(); } } class bar extends foo { private function m() { echo 'bar->m() '; } public function callbar() { $this->m(); } } $bar = new bar; $bar->call(); $bar->callbar();
现在,改变m()方法的可见性,我得到:
(为公众,私人)
Visibility bar->call() bar->callbar() ====================================================== -foo->m(),-bar->m() foo->m() bar->m() -foo->m(),+bar->m() foo->m() bar->m() +foo->m(),-bar->m() ERROR ERROR +foo->m(),+bar->m() bar->m() bar->m()
(保护似乎像公共行为).
我期待所有的事情都会像两者被宣布为公开时一样.但是,尽管foo> call()和bar-> callbar()基本上是一样的,但根据foo和bar中m()的可见性,它们会产生不同的结果.为什么会发生这种情况?
>复制;维护原有功能的范围.
>替换(“覆盖”,如果需要).
<?PHP class A { //calling B::h,because static:: resolves to B:: function callH() { static::h(); } private function h() { echo "in A::h"; } } class B extends A { //not necessary; just to make explicit what's happening function callH() { parent::callH(); } } $b = new B; $b->callH();
现在如果你重写私有方法,它的新作用域不会是A,它将是B,并且调用将失败,因为A :: callH()运行在范围A:
<?PHP class A { //calling B::h,because static:: resolves to B:: function callH() { static::h(); } private function h() { echo "in A::h"; } } class B extends A { private function h() { echo "in B::h"; } } $b = new B; $b->callH(); //fatal error; call to private method B::h() from context 'A'
这里规定如下:
>在方法表中查看对象的实际类(在你的情况下,bar).
>如果这产生私有方法:
>如果定义方法的范围与调用函数的范围相同,并且与对象的类相同,请使用它.
>否则,在父类中查找与调用函数和相同名称相同的范围的私有方法.
>如果没有找到符合上述要求的方法,则失败.
>如果这产生一个public / protected方法:
>如果方法的范围被标记为已更改,我们可能会使用public / protected方法覆盖私有方法.所以在这种情况下,如果另外还有一个方法的名称是私有的,就像为调用函数的范围所定义的一样,那么可以使用这个方法.
>否则,使用find方法.
结论
>(Both private)对于bar-> call(),调用的范围是foo.调用$this-> m()在m的方法表中引发查找,产生一个私有的bar :: m().但是,bar :: m()的范围与调用范围不同,即foo.在遍历层次结构时会发现方法foo:m(),而代之以使用.>(私人在foo,公共在酒吧)呼叫的范围仍然是foo.查找产生一个公共bar :: m().但是,其范围被标记为已更改,因此在方法m()的调用范围foo的功能表中进行查找.这产生一个私有方法foo:m()与调用范围相同的范围,所以它被使用.>没有看到这里,错误,因为可见性降低.>(Both public)调用的范围还是foo.查找产生一个公共bar :: m().它的范围没有被标记为已更改(它们都是public的),因此使用bar :: m().