Php 从类内静态调用实例方法
根据其中一个手册页: 静态调用非静态方法会生成E_严格级别警告 但是,当调用从类内部发出时,情况似乎并非如此:Php 从类内静态调用实例方法,php,Php,根据其中一个手册页: 静态调用非静态方法会生成E_严格级别警告 但是,当调用从类内部发出时,情况似乎并非如此: error_reporting(-1); class Test { private $id; function __construct($id) { $this->id = $id; } function id() { return $this->id; } function __toString() { return T
error_reporting(-1);
class Test {
private $id;
function __construct($id) { $this->id = $id; }
function id() { return $this->id; }
function __toString() {
return Test::id()
. self::id()
. static::id()
. static::id()
. call_user_func('Test::id')
. call_user_func(array('Test', 'id'));
}
}
$a = new Test('a');
$b = new Test('b');
echo "$a $b $a"; # aaaaaa bbbbbb aaaaaa
var_dump(error_get_last()); # NULL
使用PHP5.4进行测试
演示:
我相信我已经证明了:
- 未生成E_严格警告
- php神奇地将静态方法调用更正为实例方法调用(访问实例变量
证明了这一点)id
->
,意思是“方法调用”
这是一个bug,还是一个记录在案的功能?我认为它是:
在非静态上下文中,被调用的类将是
对象实例。因为$this->将尝试从调用私有方法
相同的作用域,使用static::可能会得到不同的结果。另一个
区别在于static::只能引用静态属性
换句话说(据我所知),它可以用于实现后期静态绑定:如果在扩展测试的某个类中调用它们,则使用
self::id()
和static::id()
可能会给出不同的结果。如果在任何类(而不仅仅是声明类)中使用静态语法调用非静态函数,非静态函数的行为就像是在当前$this对象的上下文中调用它一样
这意味着我可以在我的类中使用来自其他类的方法,这些方法将假定我的类的$this是他们的类的$this。如果他们不检查InstanceOf
或get_class()
,他们的行为将与平常完全相同
当我说“像往常一样”时,我的意思是他们会假设您的类“$this具有他们的类“$this将具有的所有其他方法和属性
这(我认为)被称为对象上下文绑定。在JavaScript中,您必须使用那些call()
和/或apply()
方法来获取函数,使其表现得像附加到某个对象一样。但在PHP中,它只是在非静态函数上使用静态语法
<>我记得这也是C++中的工作,但是我不记得它是否只在继承的类中使用(可能是被重写的方法,尽管它们被重写了,但是你想访问)。
使用此(隐藏)功能,您可以实现装饰器设计模式,通过该模式,您可以在运行时向对象添加新功能。您还可以模拟Mixins或Traits(PHP5.4现在本机支持)另外,这个实现是在运行时处理的,因此可以动态地完成/撤消,而语言功能实现是在编译时处理的,不能动态地完成/撤消,因此您必须更改代码来更改功能