php – 超越私有方法时的奇怪行为

前端之家收集整理的这篇文章主要介绍了php – 超越私有方法时的奇怪行为前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
考虑以下代码
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中,子类中的方法(包括私有的)可以是:

>复制;维护原有功能的范围.
>替换(“覆盖”,如果需要).

您可以使用以下代码查看此代码

<?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().

猜你在找的PHP相关文章