一式散、閉包總結(jié)
把一個(gè)閉包轉(zhuǎn)換為某個(gè)類的方法(只是這個(gè)方法不需要通過對(duì)象調(diào)用), 這樣閉包中的$this崔涂、static非剃、self就轉(zhuǎn)換成了對(duì)應(yīng)的對(duì)象或類
把閉包當(dāng)成對(duì)象的成員方法或者靜態(tài)成員方法.
Closure::bind($cl1, null, 'A'); //就相當(dāng)于在類里面加了個(gè)靜態(tài)成員方法
Closure::bind($cl2, new A(), 'A'); //相當(dāng)于在類里面加了個(gè)成員方法
成員方法中使用$this訪問對(duì)象, 靜態(tài)成員方法直接使用類名::成員的方法.
但是因?yàn)槭悄涿瘮?shù), 沒有函數(shù)名, 所以返回一個(gè)已經(jīng)綁定$this對(duì)象和類作用域的閉包給你使用.
二、閉包基本用法
閉包(Closure)又叫做匿名函數(shù)肺缕,也就是沒有定義名字的函數(shù)邑时。比如下面的例子:
// 定義一個(gè)閉包奴紧,并把它賦給變量 $f
$f = function () {
return 7;
}
// 使用閉包也很簡(jiǎn)單
$f(); //這樣就調(diào)用了閉包特姐,輸出 7
// 當(dāng)然更多的時(shí)候是把閉包作為參數(shù)(回調(diào)函數(shù))傳遞給函數(shù)
function testClosure (Closure $callback) {
return $callback();
}
// $f 作為參數(shù)傳遞給函數(shù) testClosure晶丘,如果是普遍函數(shù)是沒有辦法作為testClosure的參數(shù)的
testClosure($f);
// 也可以直接將定義的閉包作為參數(shù)傳遞,而不用提前賦給變量
testClosure (function () {
return 7;
});
// 閉包不止可以做函數(shù)的參數(shù)唐含,也可以作為函數(shù)的返回值
function getClosure () {
return function () { return 7; };
}
$c = getClosure(); // 函數(shù)返回的閉包就復(fù)制給 $c 了
$c(); // 調(diào)用閉包浅浮,返回 7
三、閉包類(Closure)
定義一個(gè)閉包函數(shù)捷枯,其實(shí)是產(chǎn)生了一個(gè)閉包類(Closure)的對(duì)象滚秩,Closure 類摘要如下
Closure {
public static Closure bind (Closure $closure , object $newthis [, mixed $newscope = 'static' ])
public Closure bindTo (object $newthis [, mixed $newscope = 'static' ])
}
方法說明:
Closure::bind: 復(fù)制一個(gè)閉包,綁定指定的 $this 對(duì)象和類作用域淮捆。
Closure::bindTo: 復(fù)制當(dāng)前閉包對(duì)象郁油,綁定指定的 $this 對(duì)象和類作用域。
下面將介紹 **Closure::bind **和 Closure::bindTo
參數(shù)和返回值說明:
closure:表示需要綁定的閉包對(duì)象攀痊。
newthis:表示需要綁定到閉包對(duì)象的對(duì)象桐腌,或者 NULL 創(chuàng)建未綁定的閉包。
newscope:表示想要綁定給閉包的類作用域苟径,可以傳入類名或類的示例案站,默認(rèn)值是'static', 表示不改變棘街。
該方法成功時(shí)返回一個(gè)新的 Closure 對(duì)象蟆盐,失敗時(shí)返回 FALSE。
class Animal {
private static $cat = "cat";
private $dog = "dog";
public $pig = "pig";
}
/*
* 獲取Animal類靜態(tài)私有成員屬性
*/
$cat = static function() {
return Animal::$cat;
};
/*
* 獲取Animal實(shí)例私有成員屬性
*/
$dog = function() {
return $this->dog;
};
/*
* 獲取Animal實(shí)例公有成員屬性
*/
$pig = function() {
return $this->pig;
};
$bindCat = Closure::bind($cat, null, new Animal());// 給閉包綁定了Animal實(shí)例的作用域遭殉,但未給閉包綁定$this對(duì)象
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 給閉包綁定了Animal類的作用域石挂,同時(shí)將Animal實(shí)例對(duì)象作為$this對(duì)象綁定給閉包
$bindPig = Closure::bind($pig, new Animal());// 將Animal實(shí)例對(duì)象作為$this對(duì)象綁定給閉包,保留閉包原有作用域
echo $bindCat(),'<br>';// 根據(jù)綁定規(guī)則,允許閉包通過作用域限定操作符獲取Animal類靜態(tài)私有成員屬性
echo $bindDog(),'<br>';// 根據(jù)綁定規(guī)則险污,允許閉包通過綁定的$this對(duì)象(Animal實(shí)例對(duì)象)獲取Animal實(shí)例私有成員屬性
echo $bindPig(),'<br>';// 根據(jù)綁定規(guī)則痹愚,允許閉包通過綁定的$this對(duì)象獲取Animal實(shí)例公有成員屬性
// bindTo與bind類似,是面向?qū)ο蟮恼{(diào)用方式,這里只舉一個(gè)里伯,其他類比就可以
$bindCat = $cat->bindTo(null, 'Animal');
以上示例輸出:
cat
dog
pig
四城瞎、連接閉包和外界變量的關(guān)鍵字:USE
閉包可以保存所在代碼塊上下文的一些變量和值。PHP在默認(rèn)情況下疾瓮,匿名函數(shù)不能調(diào)用所在代碼塊的上下文變量脖镀,而需要通過使用 use 關(guān)鍵字。
function getMoney() {
$rmb = 1;
$dollar = 6;
$func = function() use ( $rmb ) {
echo $rmb;
echo $dollar;
};
$func();
}
getMoney();
//輸出:
//1
//報(bào)錯(cuò)狼电,找不到dorllar變量
可以看到蜒灰,dollar沒有在 use 關(guān)鍵字中聲明,在這個(gè)匿名函數(shù)里也就不能獲取到它肩碟,所以開發(fā)中要注意這個(gè)問題强窖。
有人可能會(huì)想到,是否可以在匿名函數(shù)中改變上下文的變量削祈,但我發(fā)現(xiàn)是不可以的:
function getMoney() {
$rmb = 1;
$func = function() use ( $rmb ) {
echo $rmb;
//把$rmb的值加1
$rmb++;
};
$func();
echo $rmb;
}
getMoney();
//輸出:
//1
//1
原來use所引用的也只不過是變量的一個(gè)副本而已翅溺。但是我想要完全引用變量,而不是復(fù)制髓抑。要達(dá)到這種效果咙崎,其實(shí)在變量前加一個(gè) & 符號(hào)就可以了:
function getMoneyFunc() {
$rmb = 1;
$func = function() use ( &$rmb ) {
echo $rmb;
//把$rmb的值加1
$rmb++;
};
return $func;
}
$getMoney = getMoneyFunc();
$getMoney();
$getMoney();
$getMoney();
//輸出:
//1
//2
//3