Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/240.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 从类内静态调用实例方法_Php - Fatal编程技术网

Php 从类内静态调用实例方法

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

根据其中一个手册页:

静态调用非静态方法会生成E_严格级别警告

但是,当调用从类内部发出时,情况似乎并非如此:

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
    证明了这一点)
编辑- 我想在uu-toString调用中插入()会产生一个调用“type”,即
->
,意思是“方法调用”

这是一个bug,还是一个记录在案的功能?

我认为它是:

在非静态上下文中,被调用的类将是 对象实例。因为$this->将尝试从调用私有方法 相同的作用域,使用static::可能会得到不同的结果。另一个 区别在于static::只能引用静态属性


换句话说(据我所知),它可以用于实现后期静态绑定:如果在扩展测试的某个类中调用它们,则使用
self::id()
static::id()
可能会给出不同的结果。

如果在任何类(而不仅仅是声明类)中使用静态语法调用非静态函数,非静态函数的行为就像是在当前$this对象的上下文中调用它一样

这意味着我可以在我的类中使用来自其他类的方法,这些方法将假定我的类的$this是他们的类的$this。如果他们不检查
InstanceOf
get_class()
,他们的行为将与平常完全相同

当我说“像往常一样”时,我的意思是他们会假设您的类“$this具有他们的类“$this将具有的所有其他方法和属性

这(我认为)被称为对象上下文绑定。在JavaScript中,您必须使用那些
call()
和/或
apply()
方法来获取函数,使其表现得像附加到某个对象一样。但在PHP中,它只是在非静态函数上使用静态语法

<>我记得这也是C++中的工作,但是我不记得它是否只在继承的类中使用(可能是被重写的方法,尽管它们被重写了,但是你想访问)。 使用此(隐藏)功能,您可以实现装饰器设计模式,通过该模式,您可以在运行时向对象添加新功能。您还可以模拟MixinsTraits(PHP5.4现在本机支持)另外,这个实现是在运行时处理的,因此可以动态地完成/撤消,而语言功能实现是在编译时处理的,不能动态地完成/撤消,因此您必须更改代码来更改功能