<?php class myClass { private $name = "myClass"; public function echoName(){ echo $this->name; } public function getName(){ $this->echoName(); } } class newClass { private $name = "newClass"; public function echoName(){ echo $this->name; } public function test() { myClass::getName(); echo "\n"; } } $app = new newClass(); $app->test();
这个代码的最终调用结果是什么呢?(运行环境PHP 5.3.10 )
返回PHP Strict Standards Error。熟悉php的人应该知道,Strict Error是php的编码标准化警告,一般是由于php为了保持向前兼容而报出的错误。那这么说,非静态函数的静态调用在php5.3之前的某个版本是允 许的,只是在后面的版本是不被建议使用!!
如果你现在将Strict Error在error_reporting中注释掉,返回结果就变成了newClass!!
这个是为什么呢?按照我们的理解,即使调用的是myClass的getName()方法,返回的也应该是“myClass”,为什么会是“newClass”呢?
什么是静态调用?并不是说有::就是静态调用,而是看calling scope。
在PHP中, 调用一个方法的时候, $this指针指向的对象就是这个方法被调用时刻的calling scope.
<?php Foo::bar(); ?>
在调用bar方法的时候, 处于一个没有calling scope域的上下文中, 所以这个是静态调用.
而对于如下的例子:
<?php class A { public function test() { Foo::bar(); } } $a = new A(); $a->test();
在调用bar方法的时候, 处于一个$a对象的上下文中, 也就是说, 此时的calling scope是$a对象, 所以这个其实不是静态调用.
为了验证这一个结论, 请看下面的一个实际例子:
<?php class Foo { public function bar() { var_dump($this); } } class A { public function test() { Foo::bar(); } } $a = new A(); $a->test(); ?> 输出: object(A)#1 (0) { }
在调用bar的时候, 这个看似”静态”调用的调用, $this指针却是被赋值的, 指向的是$a对象, 那么这个还算静态调用么?
出现这样的问题是因为,在一个有calling scope的上下文中采用”静态的形式”调用了一个类的非静态方法所致.
<?php class A { public function __construct() { } } class B extends A { public function __construct() { parent::__construct(); } }
当我们调用父类的构造函数的时候, 我们是有意的要把当前的scope传递给父类的构造函数作为calling scope的(这里的parent::_construct()是子类将calling scope转化为父类A的calling scope。这个并不是静态调用)
静态调用是没有calling scope的,非静态调用this指向的对象就是calling scope。
Calling scope是当每一句调用的时候被传递的。
这个时候由于没有使用parent这样的关键字,也没有对this重新赋值, calling scope任然是app,就是说这个时候,所有出现的this指针指向的都是app的。
echo $this->name; 自然就是调用calling scope的name属性了。