• PHP的后期静态绑定


    参考:https://blog.csdn.net/lamp_yang_3533/article/details/79912453

    1.定义

    后期静态绑定(也叫延迟静态绑定),可用于在继承范围内引用静态调用的类

    2.工作原理

    static 后期静态绑定的工作原理是存储了上一个非转发调用(non-forwarding call)的类名
    • 当进行静态方法调用时,该类名(static指向的类名)为明确指定的那个(通常是 :: 运算符的左侧部分),即实际调用时的类。
    • 当进行非静态方法调用时,即为该对象所属的类。
    • "后期绑定"的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。

    3.转发调用

    所谓的转发调用(forwarding call)指的是通过以下几种方式进行的静态调用:self::parent::static:: 以及 forward_static_call() 。
    
    可用 get_called_class() 函数被调用的方法所在的类名。

     4.非转发调用

    通过具体的类名或具体的对象进行的调用都是非转发调用,即非上面四种方式的调用都是非转发调用。

    5.非静态环境下$this和static调用的区别

    ①$this 会优先寻找所在定义范围(父类)中的私有方法,如果存在就调用。
    ②static 是先到它指向的类(子类)中寻找私有方法,如果找到了就会报错,因为私有方法只能在它所定义的类内部调用;如果没找到,再去所在定义范围(父类)中寻找该私有方法,如果存在就调用。
    <?php
     class  A  {
        private function  foo () {
            var_dump($this); echo '--';
            var_dump(new static); echo '--';
     
            echo __CLASS__; echo '--';
            echo get_called_class();
            echo '<br>';
        }
     
        public function  test () {
            $this -> foo ();
            static:: foo ();
            echo '<br>';
        }
    }
     
    class  B  extends  A  { }
     
    class  C  extends  A  {
        private function foo () {
            echo 'this is C';
        }
    }
     
    (new  B())->test();
    (new  C())->test();
    ?>
    
    //输出结果
    object(B)#1 (0) { } --object(B)#2 (0) { } --A--B
    object(B)#1 (0) { } --object(B)#2 (0) { } --A--B
    
    object(C)#1 (0) { } --object(C)#2 (0) { } --A--C
    Fatal error: Uncaught Error: Call to private method C::foo() from context 'A' in /usercode/file.php:14 Stack trace: #0 /usercode/file.php(28): A->test() #1 {main} thrown in /usercode/file.php on line 14 
    非静态环境下$this和static调用区别

    6.后期静态绑定解析

    后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。如果静态调用使用了 parent:: 或者 self:: 等转发调用的形式,将会转发调用信息。
    <?php
    class  A  {
        public static function  foo () {
            static:: who ();
        }
     
        public static function  who () {
            echo  __CLASS__ . "
    " ;
        }
    }
     
    class  B  extends  A  {
        public static function  test () {
            A :: foo ();
            parent :: foo ();
            self :: foo ();
            static::foo();
            forward_static_call(['A', 'foo']);
            echo '<br>';
        }
     
        public static function  who () {
            echo  __CLASS__ . "
    " ;
        }
    }
     
    class  C  extends  B  {
        public static function  who () {
            echo  __CLASS__ . "
    " ;
        }
     
        public static function test2() {
            self::test();
        }
    }
     
    class  D  extends  C  {
        public static function  who () {
            echo  __CLASS__ . "
    " ;
        }
    }
     
    B::foo();
    B::test();
     
    C::foo();
    C::test();
     
    D::foo();
    D::test2();
    ?>
    
    //输出结果
    B A B B B B 
    C A C C C C 
    D A D D D D 
    后期静态绑定
  • 相关阅读:
    MFC中添加自己定义的消息
    动态创建的list control添加消息响应
    关于CString的奇怪问题
    如何去掉按钮在输入焦点切换时所产生的闪烁
    wince中将自己的应用程序编译到内核并开机启动的一种方法
    wince下圆角矩形按钮的实现
    关于error C2471:无法更新程序数据库的错误的解决方法
    关于烧写开机logo之后导致无法启动系统的问题
    利用IdHTTP进行多线程下载
    TEdit 控件的提示,就像 IE7 的地址输入栏一样
  • 原文地址:https://www.cnblogs.com/yueyun00/p/10043502.html
Copyright © 2020-2023  润新知