• static后期静态绑定


    1. 先说一下__CLASS__,get_class() ,  get_called_class() 区别:

      __CLASS__获取当前的类名,

      get_class()与上面一样,都是获取当前的类名,

      get_called_class()获取当前主调类的类名。
      参考程序:

      class A 
      {
          public function say()
          {
              echo 'a is called by'.__CLASS__.'<br/>';
              echo 'a is called by'.get_class().'<br/>';
              echo 'a is called by'.get_called_class().'<br/>';
          }
      }
      
      class B extends A
      {
          public function say()
          {
              parent::say(); //parent::调用父类中定义的成员方法
              echo 'b is called by'.__CLASS__.'<br/>';
              echo 'b is called by'.get_class().'<br/>';
              echo 'b is called by'.get_called_class().'<br/>';
          }
      }
      
      $b = new B;
      $b->say();
      View Code

        程序的运行结果是:

        a is called byA
        a is called byA
        a is called byB
        b is called byB
        b is called byB
        b is called byB

    1. 然后是static后期静态绑定介绍:(使用场景:比如  为了避免子类重写父类的属性后,使用继承的方法访问的仍然是父类的属性这样的问题)
      <?php
      class A {
          public static function who() {
              echo __CLASS__;
          }
          public static function test() {
              self::who();
          }
      }
      
      class B extends A {
          public static function who() {
              echo __CLASS__;
          }
      }
      
      B::test();
      ?>
      
      //输出 A
      
      class A {
          public static function who() {
              echo __CLASS__;
          }
          public static function test() {
              static::who(); // 后期静态绑定从这里开始
          }
      }
      
      class B extends A {
          public static function who() {
              echo __CLASS__;
          }
      }
      
      B::test();
      
      //   现在输出  B 
      View Code
      class A {
          public static function who() {
              echo __CLASS__;    // A::who()  output: A
          }
          public static function test() {
              self::who();
          }
      }
      
      class B extends A {
          public static function who() {
              echo __CLASS__;    // B::who()  output: B
          }
      }
      
      B::test();
      B::who();
      View Code

      从下面的例子中可以看出,static::存在时,test方法调用的who是B的,而不是A的,当使用self时,test方法调用的是A的who方法。

      class A {
          public static function who() {
              echo __CLASS__;
              echo 'this is A A A';
          }
          public static function test() {
              static::who(); // 后期静态绑定从这里开始,把static换成self时,输出的就是this is A A A 
          }
      }
      
      class B extends A {
          public static function who() {
              echo __CLASS__;
              echo 'this is B class';
          }
      }
      
      B::test();
      View Code

      使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。
      后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。

      class A {
          public static function foo() {
              static::who();
          }
      
          public static function who() {
              echo __CLASS__."
      ";
          }
      }
      
      class B extends A {
          public static function test() {
              A::foo();         //这个不用说,总是调用A类的foo方法
              parent::foo();    //因为是C::test(),所以当C中没有test()的时候,只能使用B的test(),以B的test()去找parent,自然找的是A中的foo
                                //而A中的foo方法里是static::who,所以去找调用他的类即C。输出C。
              self::foo();      //当B中没有foo时,只能继承A中的foo,因为这个所有的方法都是静态的,归类所有,所以在内存中只有一个,
                                //self::foo也就是A中的foo().
                                //当B中有foo() 或者C 中有foo时,结果就不一样了。
          }
      
          public static function foo() {
              echo 'this is ?';
          }
      
          public static function who() {
              echo __CLASS__."
      ";
          }
      }
      class C extends B {
          public static function who() {
              echo __CLASS__."
      ";
          }
      
          public static function foo() {
              echo 'this is ccc';
          }
      }
      
      C::test();
      View Code

      上面这个输出 “ A C this is ?”
      分析一波:因为C中没有test()方法,所以调用C::test()时,C只能继承B中的test(),而test()方法是静态的,归类所有,所以这个test()是归类B所有的,也就是说在内存中只有这一份。(B和C都指向这一个test)接下来看如何执行test(),A::foo(); 不用说肯定是调用类A中的foo方法,因为有static后期绑定,所以调用他的类实际上是C;parent::foo(); 会去找类B的父类中foo方法,也即是A中foo,同样static后期绑定,就是C调用的。再看self::foo();  手册中B没有foo方法,所以继承A中的foo方法,同样输出“C”。而这里B中是有foo方法的,所以self::foo()  调用的就是B中的foo();输出 “this is ?”。这里值的注意的是:当子类中没有重载父类的方法时,拿本题举例吧:我想表达的就是说当基类中有个静态方法时(A中有static foo),而继承他的子类没有重载该方法(B中没有foo),那么在子类中使用self::xxx();的时候(在B中使用self::foo();),self指的就是基类(self指的就是A)。同理parent也是以parent当前所在类为基础去找父类,至于不是静态的情况目前还没有思考过,parent和self都是与类有关,跟对象不发生关系。(其他的情况可以试试来验证此观点是否正确,比如在C中添加test方法)

      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();      
          }
      
          public static function foo() {
              echo 'this is ?';
          }
      
          public static function who() {
              echo __CLASS__."
      ";
          }
      }
      class C extends B {
          public static function who() {
              echo __CLASS__."
      ";
          }
      
          public static function foo() {
              echo 'this is ccc';
          }
      
          public static function test() {
              A::foo();
              parent::test();
              self::foo();
          }
      }
      
      C::test();
      //  output: " A A C this is ?this is ccc" 完全就是这个思路,没问题,如果C没有test那么他会继承B的,而现在有了test,那么self::foo执行的就是C中的foo了
      View Code

      在非静态环境下,所调用的类即为该对象实例所属的类。由于 $this-> 会在同一作用范围内尝试调用私有方法,而 static:: 则可能给出不同结果。另一个区别是 static:: 只能用于静态属性。

      class A {
          private function foo() {
              echo "success!
      ";
          }
          public function test() {
              $this->foo();
              static::foo();
          }
      }
      
      class B extends A {
         /* foo() will be copied to B, hence its scope will still be A and
          * the call be successful */
      }
      
      class C extends A {
          private function foo() {
              /* original method is replaced; the scope of the new one is C */
          }
      }
      
      $b = new B();
      $b->test();
      $c = new C();
      $c->test();   //fails
      View Code

      首先分析$b->test(); 它成功输出两个success!,当 $b调用test方法时,首先查找类B,它没有test方法,但它继承自类A,类A中有test方法,此时执行类A的test方法,所以$this是指向A的,$this->foo(),输出success,对于static::foo因为A中的foo方法是私有的,所以类B无法继承,所以此时执行的仍然是类A的foo方法,输出success。

      其次分析$c->test();当 $c调用test方法时,首先查找类C,它没有test方法,但它继承自类A,类A中有test方法,此时执行类A的test方法,所以$this是指向A的,打印$this,$this是指向对象C,$this->foo(),输出success,又因为C中有自己的foo方法,且是私有的,又因为A和C中都有foo方法,根据static的静态绑定,此时会执行类C的foo方法,由于此时的环境上下文为类A,static的作用域 为A,而static静态绑定C,要访问的foo是C作用域下的,它无法访问类C的私有方法,所以此时会报错。
      这段引用自:https://blog.csdn.net/ma199385/article/details/50639276

    2. 详细内容参考手册
  • 相关阅读:
    【20220924】双减(上)
    【20220920】连岳摘抄
    【20220918】周日的忧伤
    【20220919】连岳摘抄
    【20220922】连岳摘抄
    【20220925】双减(下)
    【20220926】人精鬼灵
    Vue Promise (回调地狱)
    Vue ES6模块化语法学习
    Vue async、await 的使用注意事项
  • 原文地址:https://www.cnblogs.com/bneglect/p/10959834.html
Copyright © 2020-2023  润新知