PHP之Closure类

@爱耍流氓的唐僧  August 18, 2020

1.Closure简介
用于代表 匿名函数 的类.

匿名函数(在 PHP 5.3 中被引入)会产生这个类型的对象。在过去,这个类被认为是一个实现细节,但现在可以依赖它做一些事情。自 PHP 5.4 起,这个类带有一些方法,允许在匿名函数创建后对其进行更多的控制。

除了此处列出的方法,还有一个 __invoke 方法。这是为了与其他实现了 __invoke()魔术方法 的对象保持一致性,但调用匿名函数的过程与它无关。

2.类摘要

Closure {
/* 方法 */
__construct ( void )
public static bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] ) : Closure
public bindTo ( object $newthis [, mixed $newscope = 'static' ] ) : Closure
}

Closure::__construct — 用于禁止实例化的构造函数
Closure::bind — 复制一个闭包,绑定指定的$this对象和类作用域。
Closure::bindTo — 复制当前闭包对象,绑定指定的$this对象和类作用域。

3.实现
PHP闭包和匿名函数使用的句法与普通函数相同,但闭包和匿名函数其实是伪装成函数的对象(Closure类的实例)。

 $closure = function($name){
            return sprintf('Hello %s', $name);
        };
        echo $closure("wudy");   //Hello wudy
        var_dump($closure instanceof Closure);   //bool(true)

以上代码创建了一个闭包对象,然后将其赋值给 closure 变量。闭包和普通的PHP函数很像,使用的句法相同,也接收参数,而且能返回值。
说明:我们之所以能够调用 $closure 变量,是因为这个变量的值是一个闭包,而且闭包对象实现了 __invoke() 魔术方法。只要变量名后有 () ,PHP就会查找并调用 __invoke() 方法。
4.实例
使用bindTo方法附加闭包状态
与其它PHP对象类似,每个闭包实例都可以使用 $this 关键字获取闭包的内部状态。闭包对象的默认状态没什么用,不过有一个 __invoke() 魔术方法和 bindTo() 方法。
bindTo() 方法为闭包增加了一些有趣的潜力。我们可以使用这个方法把 Closure 对象的内部状态绑定到其它对象上。
bindTo() 方法的第二个参数很重要,其作用是指定绑定闭包的那个对象所属的PHP类。因此,闭包可以访问绑定闭包的对象中受保护和私有的成员变量。

<?php


class TestController
{
    private $name=[];
    private $age;
    private $sex;
    //$personCallback是一个闭包对象
    public function addPerson($name, $personCallback){
        //将闭包对象绑定当前实例
        $this->name[$name] = $personCallback->bindTo($this, __CLASS__);//此处将 Closure 对象的内部状态绑定到其它对象上
    }
    public function display($name){
        foreach($this->name as $key=>$callback){
            if($key == $name){
                //执行闭包对象,将闭包状态附加到类
                $callback();
            }
        }
        echo "name:{$name}\n";
        echo "age:{$this->age}\n";
        echo "sex:{$this->sex}\n";
    }
}


$person = new TestController();
        $person->addPerson('wudy', function(){
            $this->age = 25;
            $this->sex = 'man';
        });
        
        //var_dump($person);
        //object(TestController)[1]
        // private 'name' => 
        // array (size=1)
        //    'wudy' => 
        //      object(Closure)[3]
        //       public 'this' => 
        //         &object(TestController)[1]
        // private 'age' => null
        //  private 'sex' => null
        $person->display('wudy');
        var_dump($person);
/*         object(TestController)[1]
        private 'name' => 
        array (size=1)
          'wudy' => 
            object(Closure)[3]
              public 'this' => 
                &object(TestController)[1]
        private 'age' => int 25
        private 'sex' => string 'man' (length=3)
 */

添加新评论