php5.3后静态绑定用法详解_php技巧

本文实例讲述了php5.3后静态绑定用法。分享给大家供大家参考,具体如下:

手册原文:

自 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

下面示例分析了基于PHP后期静态绑定功能解决在继承范围内引用静态调用的类。

先看如下代码:

class Person
{
public static function status()
{
self::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Deceased::status(); //Person is alive

很明显,结果不是我们预期的,这是因为self::取决于定义时所在的类,而不是运行中的类。为了解决这个问题,你可能会在继承类中重写status()方法,更好的解决方案是PHP 5.3后添加了后期静态绑定的功能。

代码如下:

class Person
{
public static function status()
{
static::getStatus();
}
protected static function getStatus()
{
echo "Person is alive";
}
}
class Deceased extends Person
{
protected static function getStatus()
{
echo "Person is deceased";
}
}
Deceased::status(); //Person is deceased

可见,static::不在指向当前所在的类,实际上,它是在运行中计算的,强制获取最终类的所有属性。

因此,建议,以后不要再使用self::,使用static::

补充:

网友帖1

php的后期静态绑定,怎么解释?下面的这幅图输出是A,C,C

由图的继承关系可知:C彻底包含了B和A。

在看答案结果以前,他细观察发现,三个类里都有同一个名称who()方法。
系统会用最后一个优先级最高,进一步的说,你几乎没法通过C去调用A、B内的who(),只能重改方法,比如添加个getBWho(){echo B::who();}
然后通过C::getBWho();来调用B内的who();

下面来看运行结果:

test只在B中出现,所以结果必然是test()中运行的三个结果:

第一个:静态直接指名到姓的调用A内静态函数,这没有悬念,必然是A
第二个:parent::是调用上一级的父类,在此题中为A,A中又直接调用static:who();上面说过了,这个who()优先级最高的在C里面,无论在你ABC中哪里调用,只要是static::who()必然是最后定义的那个,覆盖效应,如果想调用A里的必需指明A::who()或是通过去除static从作用域限制来实现。所以这个who()就是C中定义的who
第三个:self::who与第二个类似的问题,看样该走B的,注意覆盖效应,要想调用B内的who必须得B::who(),因为更高级的C已经重写了这个方法,如果C中没有who,肯定就是B,依次类推。所以必然还是调用C中的who;

所以答案为:ACC

代码如下:

<?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 B B

网友帖2

(还是针对上面图中的代码)

手册不是说得很清楚么

”后期绑定“的意思是说,static::不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为”静态绑定“,因为它可以用于(但不限于)静态方法的调用。

#1说的有个小问题

【self::foo(); // 这个self实际上是C类。明白吗? C::test() C继承了B的test()方法】

不准确,self还是B类,但是本身没有覆写foo方法,所以就调用父类A的foo方法。

如果self实际是C类,那你试下self::foo();改成self::who();,应当打印C,但是打印B,这也正是self和static的区别。

<?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::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."\n";
}
}
C::test();
?>

输出为:A C B

网友帖3

A::foo(); //A指代A类,访问A类的foo方法和who方法
parent::foo();//调用B类的父类——A的foo方法,并告诉foo方法最原始的调用者是C
self::foo(); //self指代定义该方法的类,即B,但是B没有定义foo方法,它将原始的调用者C向上传递,
// 访问父类的foo方法,最后访问c的who方法;

所以这就回答了楼上的疑问:若是把self::foo(); 改成self::who(),因为self指代B,而B有who方法,所以结果是变成了B

静态调用使用 parent:: 或者 self:: 将转发原始调用信息。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php面向对象程序设计入门教程》、《PHP基本语法入门教程》、《PHP运算与运算符用法总结》、《PHP网络编程技巧总结》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索php5.3
后静态绑定
条件函数if的用法详解、英语宾语从句用法详解、英语动词时态用法详解、scrapy rule 用法详解、英语名词用法详解,以便于您获取更多的相关知识。

时间: 2024-11-05 04:49:19

php5.3后静态绑定用法详解_php技巧的相关文章

php图像处理函数imagecopyresampled用法详解_php技巧

本文实例讲述了php图像处理函数imagecopyresampled用法.分享给大家供大家参考,具体如下: 语法 复制代码 代码如下: bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h ) 参数 dst_i

php.ini中的php-5.2.0配置指令详解_php技巧

;; 关于php.ini ;;  这个文件必须命名为'php.ini'并放置在httpd.conf中的PHPIniDir指令指定的目录中. ; 最新版本的php.ini可以在下面两个位置查看: ; http://cvs.php.net/viewvc.cgi/php-src/php.ini-recommended?view=co ; http://cvs.php.net/viewvc.cgi/php-src/php.ini-dist?view=co ;;;;;;;;;;;; ;; 语法 ;; ;;

基于php split()函数的用法详解_php技巧

PHP函数split()的基本语法为:array split ( string $pattern, string $string [, int $limit] ).我们向大家举了两个例子来具体讲解这个函数的使用方法. 对于初学者来说,掌握PHP中常用函数的用法,是其继续学习的基础.今天我们就为大家详细介绍有关PHP函数split()的一些使用方法,希望大家能通过这篇文章介绍的内容增加自己的知识库.说明array split ( string $pattern, string $string [,

PHP之sprintf函数用法详解_php技巧

本文实例讲述了PHP中sprintf函数的用法.分享给大家供大家参考.具体用法分析如下: sprintf()函数在php官方是说把字符串格式化输出了,本文就来给各位朋友介绍一下在学习sprintf()函数时的一些经验分享,希望能给大家带来帮助. PHP函数 sprintf() 函数官方定义为:sprintf():把格式化的字符串写入一个变量中 语法为:sprintf(format,arg1,arg2,arg++); 参数: format:必须,转换格式 arg1 :必须,规定插入 format

php中Ctype函数用法详解_php技巧

本文实例分析了php中Ctype函数用法.分享给大家供大家参考.具体分析如下: Ctype函数是Php的Ctype扩展函数提供了一组函数用于校验字符串中的字符是否是正确的格式,这里我们主要介绍一下这些字符串验证函数的语法.有什么特殊的函数,如何去验证等. Ctype函数是PHP内置的字符串体测函数,主要有以下几种: ctype_alnum -- Check for alphanumeric character(s):检测是否是只包含[A-Za-z0-9] ctype_alpha -- Check

PHP中strtr字符串替换用法详解_php技巧

本文实例讲述了PHP中strtr字符串替换用法.分享给大家供大家参考.具体分析如下: strtr(string,from,to)或者strtr(string,array) 首先针对strtr函数第一种方式,我们看看下面的举例,代码如下: 复制代码 代码如下: <?php echo strtr("I Love you","Lo","lO"); ?> 得到的结果是: 1 I lOve yOu 这个结果提醒我们,1.strtr它是区分大小写

javascript some()函数用法详解_php技巧

参数说明 callback: 要对每个数组元素执行的回调函数. thisObject : 在执行回调函数时定义的this对象. 功能说明 对数组中的每个元素都执行一次指定的函数(callback),直到此函数返回 true,如果发现这个元素,some 将返回 true,如果回调函数对每个元素执行后都返回 false ,some 将返回 false.它只对数组中的非空元素执行指定的函数,没有赋值或者已经删除的元素将被忽略. 回调函数可以有三个参数:当前元素,当前元素的索引和当前的数组对象. 如参数

探讨php中header的用法详解_php技巧

 header() is used to send raw HTTP headers. See the HTTP/1.1 specification for more information on HTTP headers. 范例一: 复制代码 代码如下: <?PHPHeader("Location: http://www.jb51.net";); exit;//在每个重定向之后都必须加上"exit",避免发生错误后,继续执行.?> 复制代码 代码如下:

php中strtotime函数用法详解_php技巧

本文实例讲述了php中strtotime函数用法.分享给大家供大家参考.具体如下: strtotime(字符串$时间[,诠释$现在])int strtotime(string $time [,int $now] 该函数期望得到一个包含美国英语日期格式,并会尝试解析成一个Unix时间戳(多少秒自1970年1月1日00:00:00星期一该格式),相对于现在提供的时间戳,或当前时间如果现在不提供 这个函数将使用TZ环境变量(如果有)来计算时间戳,自PHP 5.1.0有更容易的方法来确定所使用的所有/日