后期静态绑定

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

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

该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
self:: 的限制 使用 self:: 或者 __CLASS__ 对当前类的静态引用,取决于定义当前方法所在的类: Example #1 self:: 用法
<?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 后期静态绑定的用法 后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。 Example #2 static:: 简单用法
<?php
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 Note: 在非静态环境下,所调用的类即为该对象实例所属的类。由于 $this-> 会在同一作用范围内尝试调用私有方法,而 static:: 则可能给出不同结果。另一个区别是 static:: 只能用于静态属性。 Example #3 非静态环境下使用 static::
<?php
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
?> 以上例程会输出: success!
success!
success! Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9 Note: 后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。 Example #4 转发和非转发调用
<?php
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

静态绑定 self 和 static的区别的更多相关文章

  1. php self与static的区别

    self vs static 用一个demo来直接说明self与static的区别.self示例: <?phpclass Vehicle {    protected static $name ...

  2. 转:C++ 匿名namespace的作用以及它与static的区别

    匿名namespace的作用以及它与static的区别 一.匿名namespace的作用在C语言中,如果我们在多个tu(translation unit)中使用了同一个名字做为函数名或者全局变量名,则 ...

  3. C# 总结const、 readonly、 static三者区别:

    总结const. readonly. static三者区别: (有人问我,看似简单,我也没能立刻回答出来,总结一下,分享一下.) const:静态常量,也称编译时常量(compile-time con ...

  4. PHP中new self()和new static()的区别

    1.new static()是在PHP5.3版本中引入的新特性. 2.无论是new static()还是new self(),都是new了一个新的对象. 3.这两个方法new出来的对象有什么区别呢,说 ...

  5. PHP中new self()和new static()的区别探究

    1.new static()是在PHP5.3版本中引入的新特性. 2.无论是new static()还是new self(),都是new了一个新的对象. 3.这两个方法new出来的对象有什么区别呢,说 ...

  6. Java中主类中定义方法加static和不加static的区别

     Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在主方法调用(类名.方法),后者必须先实例化后用实例调用) 知识点:1.Getter and Setter 的应用 ...

  7. php面向对象编程self和static的区别

    在php的面向对象编程中,总会遇到 class test{ public static function test(){ self::func(); static::func(); } public ...

  8. C++ 匿名namespace的作用以及与static的区别

    匿名namespace的作用以及它与static的区别 一.匿名namespace的作用 在C语言中,如果我们在多个tu(translation unit)中使用了同一个名字做 为函数名或者全局变量名 ...

  9. vue中assets和static的区别

    Vue中assets和static的区别 再一次框架定型中,与同事在静态资源的存放上有了一些分歧,后来经过查阅总结如下: 相同点:   assets和static两个都是存放静态资源文件.项目中所需要 ...

随机推荐

  1. 关于矢量图片资源向后兼容:CompatVectorFromResourcesEnabled标志的使用

    StackOverflow上摘抄的: some things have changed since I asked this question so I will answer it myself.W ...

  2. 【转】WCF入门教程二[WCF应用的通信过程]

    一.概述 WCF能够建立一个跨平台的安全.可信赖.事务性的解决方案,是一个WebService,.Net Remoting,Enterprise Service,WSE,MSMQ的并集,有一副很经典的 ...

  3. 在Delphi中编写res文件

    delphiimagedosinterfaceborland脚本先用记事本编写一个rc的文件. 如内容为: _Comms RCData Comms.jpg Comms.jpg为图片名称, 然后在这个r ...

  4. javaScript实现归并排序

    归并排序是一个O(nlogn)的算法,其基本思想就是一个分治的策略,先进行划分,然后再进行合并,下面举个例子.有这样一组数据: {5,4,1,22,12,32,45,21} 如果对它进行归并排序的话, ...

  5. Unity获取指定资源目录下的所有文件

    使用前需要引入System.IO;这个命名空间 public void GetFiles() { //路径 //string path = string.Format("{0}", ...

  6. oracle函数学习_根据用户id获取用户角色

    create or replace function FN_GET_ROLES(v_user_id varchar2) return varchar2 istype zy_emp_cursor is ...

  7. Linux 同步方法剖析--内核原子,自旋锁和相互排斥锁

    在学习 Linux® 的过程中,您或许接触过并发(concurrency).临界段(critical section)和锁定,可是怎样在内核中使用这些概念呢?本文讨论了 2.6 版内核中可用的锁定机制 ...

  8. Java精选笔记_Java编程基础

    Java的基本语法 Java代码的基本格式 修饰符 class 类名 {   程序代码 } 一个Java源文件只定义一个类,不同的类使用不同的源文件定义:将每个源文件中单独定义的类都定义成public ...

  9. centos无法联网解决方法

    1)进入 /etc/sysconfig/network-scripts/ 2)vi 或 vim 打开 ifcfg-eth0(不一定是eth0,这个自己判断了) 3)将 ONBOOT=no 改成 ONB ...

  10. hadoop程序MapReduce之SingletonTableJoin

    需求:单表关联问题.从文件中孩子和父母的关系挖掘出孙子和爷奶关系 样板:child-parent.txt xiaoming daxiong daxiong alice daxiong jack 输出: ...