PHP 闭包(Closure)

一、闭包基本用法
闭包(Closure)又叫做匿名函数,也就是没有定义名字的函数。比如下面的例子:

// 定义一个闭包,并把它赋给变量 $f
$f = function () {
    return 7;
}

// 使用闭包也很简单
$f(); //这样就调用了闭包,输出 7

// 当然更多的时候是把闭包作为参数(回调函数)传递给函数
function testClosure (Closure $callback) {
    return $callback();
}

// $f 作为参数传递给函数 testClosure,如果是普遍函数是没有办法作为testClosure的参数的
testClosure($f);

// 也可以直接将定义的闭包作为参数传递,而不用提前赋给变量
testClosure (function () {
    return 7;
});

// 闭包不止可以做函数的参数,也可以作为函数的返回值
function getClosure () {
    return function () { return 7; };
}

$c = getClosure(); // 函数返回的闭包就复制给 $c 了
$c(); // 调用闭包,返回 7

二、闭包类(Closure)
定义一个闭包函数,其实是产生了一个闭包类(Closure)的对象,Closure 类摘要如下:

Closure {   
    public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])  
    public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])  
} 

方法说明:
Closure::bind: 复制一个闭包,绑定指定的 $this 对象和类作用域。
Closure::bindTo: 复制当前闭包对象,绑定指定的 $this 对象和类作用域。
下面将介绍 Closure::bind 和 Closure::bindTo
参数和返回值说明:
closure:表示需要绑定的闭包对象。
newthis:表示需要绑定到闭包对象的对象,或者 NULL 创建未绑定的闭包。
newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例,默认值是'static', 表示不改变。
该方法成功时返回一个新的 Closure 对象,失败时返回 FALSE。

class Animal {  
    private static $cat = "cat";  
    private $dog = "dog";  
    public $pig = "pig";  
}  

/*  
 * 获取Animal类静态私有成员属性 
 */  
$cat = static function() {  
    return Animal::$cat;  
};  

/*  
 * 获取Animal实例私有成员属性 
 */  
$dog = function() {  
    return $this->dog;  
};  

/*  
 * 获取Animal实例公有成员属性 
 */  
$pig = function() {  
    return $this->pig;  
};  

$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象  
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包  
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域  
echo $bindCat(),'<br>';// 根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性  
echo $bindDog(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性  
echo $bindPig(),'<br>';// 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性

// bindTo与bind类似,是面向对象的调用方式,这里只举一个,其他类比就可以
$bindCat = $cat->bindTo(null, 'Animal');

最后举一个 PHP 官网给出的例子

class A {
    function __construct($val) {
        $this->val = $val;
    }
    function getClosure() {
        //returns closure bound to this object and scope
        return function() { return $this->val; };
    }
}

$ob1 = new A(1);
$ob2 = new A(2);

$cl = $ob1->getClosure();
echo $cl(), "\n";
$cl = $cl->bindTo($ob2);
echo $cl(), "\n";

以上示例输出:

1
2
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 7年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 5

原来是抄的别人的,都没抄全!

7年前 评论
qiuyuhome

下面这句话有错别字。看了一下原文,也是错的。复制粘贴大法?
newscope:表示想要绑定给闭包的类作用域,可以传入类名或类的示例实例,默认值是'static', 表示不改变。

7年前 评论