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();

    程序的运行结果是:

    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
    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();

    从下面的例子中可以看出,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();

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

    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(); //这个不用说,总是调用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__."\n";
    }
    }
    class C extends B {
    public static function who() {
    echo __CLASS__."\n";
    } public static function foo() {
    echo 'this is ccc';
    }
    } C::test();

    上面这个输出 “ 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__."\n";
    }
    } 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__."\n";
    }
    }
    class C extends B {
    public static function who() {
    echo __CLASS__."\n";
    } 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了

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

    class A {
    private function foo() {
    echo "success!\n";
    }
    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

    首先分析$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. 详细内容参考手册

static后期静态绑定的更多相关文章

  1. 139-PHP static后期静态绑定(二)

    <?php class test{ //创建test类 public function __construct(){ static::getinfo(); //后期静态绑定 } public s ...

  2. 138-PHP static后期静态绑定(一)

    <?php class test{ //创建test类 public function __construct(){ self::getinfo(); //后期静态绑定 } public sta ...

  3. PHP的后期静态绑定

    self 是个孝子 不管后来 谁是它的领导(调用它)  谁生了它  它就听谁的 子类调用父类的方法 self 的生存空间是父类 不管是不是子类调用 我生在哪 我就在哪个类里面找属性/方法 static ...

  4. PHP之后期静态绑定

    PHP后期静态绑定的(late static bindings) 理解PHP延迟静态绑定 static::中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名.这个东西可以实现在父类 ...

  5. php中的后期静态绑定

    后期静态绑定PHP手册 使用的保留关键字: static 定义: static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的.也可以称之为"静态绑定",因为它可以用 ...

  6. php后期静态绑定

    php后期静态绑定 自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类. 虽然也可以调用非静态方法,但是不会在运行时绑定. static 不再只是简 ...

  7. php中的后期静态绑定("Late Static Binding")

    在我们以往中,在类中使用self关键字的时候都是指向了被调用方法定义时的类,而非原始的调用类. 例如: class Animal{ static $IQ_lv_avg = 1; public stat ...

  8. php static延迟静态绑定

    如果你是一个懒惰的程序员,你看到以下代码可能会恼火 abstract class U{ } class u1 extends U{ public static function create(){ r ...

  9. PHP 之 this self parent static 对比

    this 绑定的是当前已经实例化的对象 这样长出现的问题: 如果你在一个父类中使用$this调用当前一个类的方法或者属性,如果这个类被继承,且在相应的子类中有调用的属性或者方法是,则父类中的$this ...

随机推荐

  1. 基于硬件的消息队列中间件 Solace 简介之二

    前言...... 前面简单介绍了Solace来自于哪家公司, 主要能做哪些事情. 本篇主要进一步介绍Solace作为消息传递的中间件如何工作的. 传统意义上来讲, 每当我们谈到消息中间件时, 首先想到 ...

  2. Tomcat开机自启动,通过服务名重启

    1.将Tomcat注册为服务2.服务开机自启动3.修改Tomcat进程名(待补充)4.通过命令查看日志,不需要进入到日志目录(待补充)5.tomcat进程守护(待补充) 1. 安装tomcat, 此处 ...

  3. make j* make j4 make j8 区别

    转载: make -j4是什么意思看书上说1) make(1)只衍生一个作业//作业是什么意思?make(1) 是不是就是make的意思?2) 在双处理器上make -j4,难道是让每个处理器跑两个作 ...

  4. PTA(Basic Level)1021.个位数统计

    给定一个 k 位整数 \(N=d_{k−1}10^{k−1}+⋯+d_110^1+d_0 (0≤d_i≤9, i=0,⋯,k−1, d_{k−1}>0)\),请编写程序统计每种不同的个位数字出现 ...

  5. PTA(Basic Level)1041.考试座位号

    每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位.正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考 ...

  6. Springboot---后台导出功能,easyExcel

    Sprintboot+vuejs+easyExcel实现excel导出功能 一.背景 前段时间,有个需求,想要做一个excel导出功能,用来把查询到的数据进行导出.第一次做,所以搜了大量的资料,分为两 ...

  7. Linux学习笔记(16)Linux前后台进程切换(fg/bg/jobs/ctrl+z)

    关键词:Linux前后台进程切换,linux进程切换 fg.bg.jobs.&.ctrl + z都是跟系统任务有关的,虽然现在基本上不怎么需要用到这些命令,但学会了也是很实用的一.& ...

  8. 设计模式:职责链模式(Chain of Responsibility)

    去年参加校招要到长沙来,这个对于我来说不是特别喜欢(但又必须的来,谁叫咱不是985.211的娃呢),但是对于某些人来说就是福音了.大四还有课,而且学校抓的比较严,所以对于那些想翘课的人来说这个是最好不 ...

  9. CSP 画图(201512-3)

    问题描述 用 ASCII 字符来画图是一件有趣的事情,并形成了一门被称为 ASCII Art 的艺术.例如,下图是用 ASCII 字符画出来的 CSPRO 字样. ..____.____..____. ...

  10. 版本控制器之SVN(二)

    安装重启以后,在菜单栏找到TortoiseSVN程序 启动以后 点击: 填写相应的信息: 可以看到项目的相关信息 选中仓库,右键 > Browse Repository 进入如下界面: 可以打开 ...