ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

PHP 后期静态绑定

2022-03-28 18:32:33  阅读:183  来源: 互联网

标签:调用 foo 静态 绑定 static 转发 PHP


在看一些框架源码或者是某个项目的代码时,经常能看到后期静态绑定的用法
。比如下面这段:

public static function getInstance()
{
    if (is_null(static::$instance)) {
        static::$instance = new static;
    }
    return static::$instance;
}

这里用到的就是后期静态绑定。那么,什么是后期静态绑定?

“后期绑定” 的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。

这里要先说两个概念,一个是转发调用,另一个是非转发调用。

转发调用
所谓的 “转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::, parent::, static:: 以及 forward_ static _call ()。即在进行静态调用时未指名类名的调用属于转发调用。

非转发调用
非转发调用其实就是明确指定类名的静态调用(foo::bar ())和非静态调用 ($foo->bar ())。即明确地指定类名的静态调用和非静态调用。

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

在 PHP 的官方文档里,对于后期静态绑定是这样说的:后期静态绑定工作原理是存储了在上一个 “非转发调用”(non-forwarding call)中的类名。意思是当我们调用一个转发调用的静态调用时,实际调用的类是上一个非转发调用的类。

来看两个例子:

例 1:

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
例 2:

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

以上代码会输出

A
C
C
在这里主要分析下例 2。

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。

使用后期静态绑定的好处

后期静态绑定目前我看到较多的是用于对象实例化中,在实例化对象时,static 会根据运行时调用的类来决定实例化对象,而 self 则是根据所在位置的类来决定实例化对象。当我们只想实例化子类,并且不希望后续在对子类的使用中由于父类的变化对子类产生影响时,后期静态绑定就能发挥它的作用了。

————————————————
原文作者:JeffreyC
转自链接:https://learnku.com/articles/8964/understanding-of-static-binding-at-the-later-stage-of-php
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。

标签:调用,foo,静态,绑定,static,转发,PHP
来源: https://www.cnblogs.com/lis2/p/16068474.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有