根据其中一个手册页 http://www.php.net/manual/en/language.oop5.static.php :
Calling non-static methods statically generates an E_STRICT level warning.
但是,当从类内部进行调用时,情况似乎并非如此:
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
用 php 5.4 测试
演示: http://codepad.viper-7.com/IKp9iX
我相信我已经证明了:
- 没有生成 E_STRICT 警告
- 那个 php 神奇地将静态方法调用更正为实例方法调用(访问实例变量
id
证明了这一点)。
编辑-
我想添加插入 debug_backtrace () 到 __toString 调用中产生 ->
的调用“类型”,这意味着“方法调用”。
这是错误还是已记录的功能?
最佳答案
如果您在任何类(不仅仅是声明类)中使用静态语法调用非静态函数,则该非静态函数的行为就好像它被调用一样在当前 $this 对象的上下文中。
这意味着我可以在我的类中使用其他类的方法,并且这些方法将假设我类的$this是他们的类的$this强>。如果它们不检查 InstanceOf
或 get_class()
,它们的行为将与往常完全一样。
当我像往常一样说时,我的意思是他们会假定您的类的 $this 具有他们的类的 $this 将具有的所有其他方法和属性。
这(我认为)称为对象上下文绑定(bind)。在 JavaScript 中,您必须使用那些 call()
和/或 apply()
方法来使函数的行为就像它附加到某个对象一样。但在 PHP 中,它只是通过在非静态函数上使用静态语法来工作。
我记得这在 C++ 中也有效,但我不记得它是否仅在方法属于继承类时有效(尽管它们被覆盖,但您可能想要访问的覆盖方法)。
使用此(隐藏)功能,您可以实现Decorator 设计模式,通过该模式可以在运行时向对象添加新功能。您还可以模拟 Mixins 或 Traits(PHP 5.4 现在原生支持),额外的好处是此实现在运行时处理,因此可以完成/撤消与在编译时处理并且不能动态完成/撤消的语言功能实现相反,您必须更改代码才能更改功能。
关于php - 从类中静态调用实例方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11165429/