- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章php5.3后静态绑定用法详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文实例讲述了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:: 用法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?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:: 简单用法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<?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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?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 转发和非转发调用 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<?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后期静态绑定功能解决在继承范围内引用静态调用的类.
先看如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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后添加了后期静态绑定的功能.
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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 。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<?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的区别.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<?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 。
1
2
3
4
|
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程序设计有所帮助.
最后此篇关于php5.3后静态绑定用法详解的文章就讲到这里了,如果你想了解更多关于php5.3后静态绑定用法详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
最近我在用 RestSharp消耗我的 Restful 资源。并期望在服务器和客户端之间与 JSon 交换数据。下面是我的 C# 代码。 var client = new RestSharp.Rest
我正在阅读 Bartosz Milewski 的一篇文章,其中他定义了以下函数: instance Applicative Chan where pure x = Chan (repeat x)
‘…' 其实是go的一种语法糖。 它的第一个用法主要是用于函数有多个不定参数的情况,可以接受多个不确定数量的参数。 第二个用法是slice可以被打散进行传递。 实例:
前言 在算face_track_id map有感: 开始验证 data={"state":[1,1,2,2,1,2,2,2],"pop":[&quo
本文实例讲述了php访问数组最后一个元素的函数end()用法。分享给大家供大家参考。具体分析如下: end()函数在PHP中用于检索数组中的最后一个元素。end()函数需要一个数组作为其唯一参数,
我使用的是 jdk1.8.0_92。我的虚拟机如下所示。 $java -version java version "1.8.0_92" Java(TM) SE Runtime Environment
我的情况是我需要将所有匹配 http://mywebsite.com/portfolio/[anyname] 的请求定向到 http://mywebsite.com/portfolio.php?用户名
我正在尝试在 NLTK 中使用语音标记并使用了以下命令: >>> text = nltk.word_tokenize("And now for something completely differe
#include typedef QList IntList; qRegisterMetaType("IntList"); error C2909: 'qRegisterMetaType':
来自 here我知道 BN_CTX 是一个保存 BIGNUM 临时变量的结构。这些 BIGNUM 变量什么时候会进入 BN_CTX 的 BN_POOL?如果我有一个 bignum_ctx BN_CTX
尝试为 ABPersonRef 创建对象例子:ABpersonRef 引用; 已包含Addressbook和AddressBookUI框架即使这样,当我编译时,它仍显示“ABPersonRef”未声明
我无法使用 GetAltTabInfo。可能是一个愚蠢的错误,但这有什么问题呢? HWND taskSwitcher = FindWindow(L"TaskSwitcherWnd", L"Task S
JSLint4Java 是 JSLint 的 Java 包装器。我需要这样的东西在我的 GWT 项目中使用,但使用 JSLint4Java 的唯一方法似乎是从命令行或通过 ANT 任务。有谁知道是否有
我有一个持久化实体对象的方法 persistData() 。我有另一个方法 findData() ,它对同一实体类执行 find() 操作以获取持久的主键值。当我在实体类的@PostPersist中调
下面是我的代码。请查看。 1. bool isUnavailable = db.Deploys.Where(p => p.HostEnvironmentId == Guid.Parse(h
这个问题已经有答案了: Why can't a Generic Type Parameter have a lower bound in Java? (6 个回答) 已关闭 9 年前。 我试图理解为什
我正在尝试使用 scala 编译器 Y 警告,但我认为我做得不对。在下面的示例中,nums 未使用,因此我希望 -Ywarn-value-discard 打印一个警告。有两个 if 条件,一个嵌套在另
用户被要求从某个给定的集合中选择一个 ID。我检查该 ID 是否存在于我的集合中,如果不存在,我会抛出 IndexOutOfBoundsException 并稍后捕获它。我实际上可以使用该异常来达到这
我正在尝试减少从 OSM 路径数据生成的形状文件。我正在使用 VTS 的 DouglasPeuckerSimplifier 实现。我想为特定 GTFS(通用交通提要规范)构建路线图的 geojson。
我明白了?!是排除某个模式,例如 a(?!b) 表示如果“a”后面没有“b”,它将匹配“a”。我的问题是,假设我有一个包含以下内容的文件: a cat is a cat, a dog is a dog
我是一名优秀的程序员,十分优秀!