专栏首页zlmai的专栏理解PHP的延迟静态绑定

理解PHP的延迟静态绑定

static::中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名。这个东西可以实现在父类中,能够调用子类的方法和属性。

使用(static)关键字来表示这个别名,和静态方法,静态类没有半毛钱的关系,static::不仅支持静态类,还支持对象(动态类)。

转发调用

所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。

非转发调用

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

后期静态绑定原理

后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。

例子1,简单使用static::

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

分析:运行B::test()会调用B中继承自A的test方法,然后会执行static::who(),而static::中的static表示运行时所在类的别名,此时运行的类名是B,所以static::who()就是执行B中的who方法,所以输出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

分析:运行C::test()会调用C继承自B的test方法,这个方法中首先执行的是A中的foo方法,此时属于静态方法调用,static对应的类名就是明确指定的那个A类,故会输出A;然后是parent::foo()和self::foo()方法,这两个都属于转发调用,前一个调用的是B的foo方法,后一个调用的是C的foo方法,实际的执行内容都是static::foo(),当static::中的static其实是运行时所在类的别名,此时运行的类是C,所以都会输出C。

例子3,使用场景举例

class Model 
{ 
    public static function find() 
    { 
        echo static::$name; 
    } 
} 

class Product extends Model 
{ 
    protected static $name = 'Product'; 
} 

Product::find(); 

输出:

Product

分析:Product::find()方法运行的是Product继承自Model的find方法,这个方法中的static对应于此时正在执行的类名,即Product,所以相当于运行Product:: $name,输出了Product。

原文链接:https://laravel-china.org/topics/3844/understanding-php-delayed-static-binding-late-static-bindings

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++中关于几种输入方法的总结

    C++中有很多关于输入的函数,比如cin、cin.get()、cin.getline()、getline()、gets()等等,很容易搞混,下面分别总结下,欢迎...

    zlmai
  • 搞清C++中指针、数组、字符串的关系

    在一些时候,字符串、指针和数组的关系我们常常搞混,下面通过一些典型问题来展示它们间的关系。

    zlmai
  • Flask配置静态资源

    1. 简介 flask可对实例、配置模板文件路径、静态文路径进行配置 Flask(import_name, static_url_path=None, st...

    菲宇
  • 深入理解static关键字

    如果给一个属性加上static,那么这个属性不再属于某一个对象了,而是属于N个对象,共用同一个static属性。

    爱学习的孙小白
  • Java下static关键字用法详解

      本文章介绍了java下static关键字的用法,大部分内容摘自原作者,在此学习并分享给大家。

    哲洛不闹
  • Java中的static关键字解析

      static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一。下面就先讲述一下stat...

    Java团长
  • 【Java学习笔记之十五】Java中的static关键字解析

    Java中的static关键字解析   static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的...

    Angel_Kitty
  • java中static关键字的用法和注意点

    package com.javabase.keywords; public class KeyWord { static int id = 1; ...

    gfu
  • Spring boot web程序static资源放在jar外部

    spring boot程序的static目录默认在resources/static目录, 打包为jar的时候,会把static目录打包进去,这样会存在一些问题:...

    用户1177380
  • Java中static关键字的作用

    static关键字主要有两种作用: 第一,为某特定数据类型或对象分配单一的存储空间,而与创建对象的个数无关。 第二,实现某个方法或属性与类而不是对象关联在一起 ...

    程序员互动联盟

扫码关注云+社区

领取腾讯云代金券