PHP关于静态绑定的一点疑问

class A {
    public static function foo() {
        static::who();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}

class B extends A {
    public static function test() {
        A::foo();
        parent::foo();
        self::foo();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}
class C extends B {
    public static function who() {
        echo __CLASS__."\n";
    }
}

C::test();

输出结果为ACC.我的疑问是为什么第二个是C而不是B?还请各位大神赐教

阅读 2.6k
3 个回答

自己来回答一下。静态调用分为转发调用和非转发调用。
转发调用:进行静态调用时使用static::,self::,parent::,forword_static_call进行调用。换句话说就是没有指定类名的静态条用。
非转发调用:进行静态调用时使用类名::或者进行非静态调用时使用类名->方法名调用。换句话说就是明确地指定类名的静态调用和非静态调用。

再说的通俗一点,顾名思义,非转发调用前面有类名所以调用的函数一定是属于“这个类的”,不需要转到别的类。转发调用就是由于前期的静态绑定导致在后面调用静态方法时可能“转发到其他的类”。

在PHP的官方文档里,对于后期静态绑定是这样说的:后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)中的类名。意思是当我们调用一个转发调用的静态调用时,实际调用的类是上一个非转发调用的类。
现在我一步步分析上面的例子
1.C::test().毫无疑问,这是一个非转发调用,因为::前面有类名C。
2.进入test()方法,有三个静态调用A::foo(),parent::foo(),self::foo(),对于这三个静态调用来说,他们的非转发调用类就是C。
3.现在执行A::foo(),这是一个非转发调用。A::foo()中的代码是static::who,这是一个转发调用,对于这个转发调用来说他的非转发调用类就是不再是C而是A(因为之前执行了A::foo())。因此执行的结果为A
4.现在执行parent::foo(),这是一个转发调用,转发到哪里呢?就是它的上一个非转发调用的类,也就是类C(在步骤2中提到的)。在这里一定要注意虽然在这之前执行了A::foo(),但是parent::foo()的上一个非转发调用的类任然是类C。因此执行的结果是C.
5.现在执行self::foo(),这个和parent::foo()一样都是转发调用,因此也输出C。

新手上路,请多包涵

如果静态调用使用parent::或者 self::将转发调用信息,也就是运行时的调用者C

这就是静态调用static的意义啊.
你用parent或者self会显示 当前调用者 , 也就是C .
所以,才出现了static

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题