PHP 閉包(Closure)

jiazhuamh發表於2017-05-05

一、閉包基本用法
閉包(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 協議》,轉載必須註明作者和本文連結

相關文章