• 你好!欢迎你的到来
  • 关于我们
  • 首页 博客 学习笔记 技术导航 工具
  • 博文分类
    • PHP(43)
    • MySQL(11)
    • Linux(28)
    • html(3)
    • JQuery(4)
    • JavaScript(9)
    • svn(2)
    • CSS(2)
    • seajs(1)
    • go(44)
    • redis(1)
    • nginx(8)
    • mongo(0)
    • java(0)
    • 算法(0)
    • 其他(26)
    • 生活(1)
    专栏
    • Jquery基础教程
      • 文章:(15)篇
      • 阅读:27566
    • shell命令
      • 文章:(42)篇
      • 阅读:91621
    • Git教程
      • 文章:(36)篇
      • 阅读:159447
    • leetCode刷题
      • 文章:(76)篇
      • 阅读:39603
    • 摘要视图
    • 目录视图
    PHP后期静态绑定之static-parent-self
    2017-08-19 10:15 阅读(4465) 评论(3)

    概念

    关于静态绑定,手册上是这么说的:

        自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。

    准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。

        该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。

    首先看一个实例,你能全部正确的答出来吗?

    <?php
    class A {
        public static function foo() {
            static::who();
        }
    
        public static function who() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
    }
    
    class B extends A {
        public static function test() {
           
             self::who();       //self指的是当前类B,但调用者仍然是C,self只是起到转发调用者的作用,相当于C调用了B的who方法
             parent::who();     //parent指的是当前类的父类A;调用者依然是C,parent在这里,只是起到“转发调用者”的作用,是C要调用A中的Who
             static :: who();   //这里,因为调用者是C,等价于C::who()
    
             A::foo();         //将调用者改为A
             B::foo();         //将调用者改为B
             
             static::foo();    // 因为调用者是C,此时相当于C::foo();
             parent::foo();    // parent指的是当前类的父类A;调用者依然是C,parent在这里,只是起到“转发调用者”的作用,是C要调用A中的foo,在A的foo中,static::who()相当于C::who()
             self::foo();     // self指的是当前类B;调用者依然是C,self在这里,只是起到“转发调用者”的作用,是C要调用B中的foo,B中的foo继承与A,在A的foo中,static::who()相当于C::who()
        }
    
        public static function who() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
    }
    class C extends B {
        public static function who() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
    }
    
    C::test();

    执行结果如下:

    C调用了B的who

    C调用了A的who

    C调用了C的who


    A调用了A的who

    B调用了B的who


    C调用了C的who

    C调用了C的who

    C调用了C的who


    其中,get_called_class 方法,是获取后期静态绑定("Late Static Binding")类的名称,即调用者的类名,在PHP5及以上版本,可以通过static::class获取调用者的类名。

    self永远指向定义它的类。即你在哪里写了self,self就代表哪个类。

    跟self类似,parent指向的是定义它的类的父类。

    static指向了当前的调用域(calling scope),而不是定义它的地方代表的域。也就是说static绑定了调用方法的类,而不是定义方法的类。

    手册上有这么一句话:后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者self:: 将转发调用信息

    转发调用

    class A {
        public static function who() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__;
        }
        public static function test() {
            self::who();
        }
    }
    
    class B extends A {
        public static function who() {
            echo __CLASS__;
        }
    }
    B::test();

    输出结果:B调用了A的who

    static调用私有的方法

    实例1
    class A {
        private function foo() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
        public function test() {
            static::foo(); //此时调用者是B
        }
    }
    
    class B extends A {
       
    }
    
    $b = new B();
    $b->test();

    输出结果:B调用了A的foo

    手册上面说A中的 foo() will be copied to B, hence its scope will still be A ,也就是说foo方法会复制到B中,但是A是的foo是私有的方法,怎么能复制到B呢?

    我认为,static::foo首先会判断B中是否有foo方法,没有找到,然后就调用A中的私有foo。

    实例2
    class A {
        private function foo() {
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
        public function test() {
            static::foo();
        }
    }
    
    class B extends A {
       public function foo() {
            /* original method is replaced; the scope of the new one is C */
            echo get_called_class().'调用了'.__CLASS__.'的'.__FUNCTION__."\n";
        }
    }
    $b = new B();
    $b->test();

    输出结果:C调用了C的foo

    若将B中的foo方法改为私有,则会报错:PHP Fatal error:  Call to private metho

    本文为原创文章,请尊重辛勤劳动,如需转载,请保留本文地址
    http://www.findme.wang/blog/detail/id/240.html

    若您感觉本站文章不错,读后有收获,不妨赞助一下?

    我要赞助

    您还可以分享给朋友哦

    更多
    顶
    4
    踩
    0
    • 上一篇: 使用phpize为PHP添加curl扩展
    • 下一篇: PHP的ZMQ扩展zeromq源码安装
    • 查看评论
    • 正在加载中...
    • 留言
    • 亲,您还没有登录,登录后留言不需要审核哦!
      可以使用如下方式登录哦!
  • CSDN | 新浪微博 | github | 关于我们 | 我要留言 | 友链申请
  • 豫ICP备18038193号    Copyright ©lidequan All Rights Reserved