为什么将闭包从一个类传递到另一个类并从第二个类调用它会执行第一个类的代码呢


Why exactly does passing a closure from one class to another and calling it from the second class execute code from the first class?

很难为这个问题找到一个标题,但基本上这里是代码:

<?php
class Sub {
    protected $closure;
    public function setClosure($closure) {
        $this->closure = $closure;
    }
    public function callClosure() {
        $this->closure->__invoke();
    }
    protected function outcome() {
        echo 'calling from sub';
    }
}
class Main {
    public function __construct() {
        $this->sub = new Sub();
    }
    public function start() {
        $this->sub->setClosure(function() {
            $this->outcome();
        });
        $this->sub->callClosure();
    }
    protected function outcome() {
        echo 'calling from main';
    }
}
$main = new Main();
$main->start();

其结果为CCD_ 1。然而,这正是我想要的,因为我将处理这种行为,我不完全理解为什么它会以这种方式工作,我想澄清一下。

在编写代码之前,我希望它从Sub类调用outcome方法,而不是从Main类调用。闭包是否使用了定义它的范围中的$this?如果出于任何原因,我希望它在被调用的作用域中使用$this,该怎么办?

它正常工作,并根据php匿名函数手册,因为

闭包的父作用域是闭包所在的函数声明的(不一定是从中调用的函数)

在php中,这个匿名函数实现为闭包类。正如Mark Baker已经说过的,当你在Main类中创建闭包时,你会自动得到这个绑定对象和这个类范围。

"绑定对象"确定$this在函数体和"类作用域"表示一个类确定匿名函数的私有成员和受保护成员将能够访问。也就是说,可见的成员是就像匿名函数是给定类的方法一样作为newsscope参数的值。

在您的情况下,这个类是Main而不是Sub