今天小編給大家分享一下PHP閉包及Clourse類的作用是什么的相關(guān)知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

創(chuàng)新互聯(lián)是專業(yè)的蒙城網(wǎng)站建設(shè)公司,蒙城接單;提供成都網(wǎng)站制作、做網(wǎng)站、外貿(mào)營銷網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進行蒙城網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
0x00 前言
閉包是指在創(chuàng)建時封裝周圍狀態(tài)的函數(shù)。即使閉包所在的環(huán)境不存在了,閉包中封裝的狀態(tài)依然存在。
在 PHP 里所有的閉包都是 Clourse 類所實例化的一個對象,也就是說閉包與其他 PHP 對象沒有什么不同。而一個對象就必然有其方法和屬性,這篇文章將總結(jié) PHP 中閉包的基礎(chǔ)用法和 Clourse 類方法的作用。
0x01 閉包基本用法
下面看看最基本的閉包使用方法:
<?php
$hello = function ($word) {
return 'hello ' . $word;
};
echo $hello('world');
// 輸出 hello world嘿,這段代碼最直觀的感受就是將一個函數(shù)賦值給了 $hello 變量,然后通過 $hello 直接調(diào)用它。但是這個閉包并沒有從父作用域中繼承變量(就是封裝周圍狀態(tài)),我們可以通過 use 關(guān)鍵字從閉包的父作用域繼承變量。示例如下:
<?php
$name = 'panda';
$hello = function () use ($name) {
return 'hello ' . $name;
};
echo $hello();
// 輸出 hello pandaPHP 7.1 起,use 不能傳入此類變量: superglobals、 $this 或者和參數(shù)重名。
此外在使用 use 關(guān)鍵字時,父作用域的變量是通過值傳遞進閉包的。也就是說一旦閉包創(chuàng)建完成,外部的變量即使修改也不會影響傳遞進閉包內(nèi)的值(就是即使閉包所在的環(huán)境不存在了,閉包中封裝的狀態(tài)依然存在)。示例如下:
<?php
$name = 'panda';
$hello = function () use ($name) {
return 'hello ' . $name;
};
$name = 'cat';
echo $hello();
// 輸出 hello panda傳遞變量的引用可以使閉包修改外部變量的值,示例如下:
<?php
$name = 'panda';
$changeName = function () use (&$name) {
$name = 'cat';
};
$changeName();
echo $name;
// 輸出 cat注意:PHP 中傳遞對象時,默認是以引用傳遞所以在閉包內(nèi)操作 use 傳遞的對象時需要特別注意。示例如下:
<?php
class Dog {
public $name = 'Wang Cai';
}
$dog = new Dog();
$changeName = function () use ($dog) {
$dog->name = 'Lai Fu';
};
$changeName();
echo $dog->name;
// 輸出 Lai Fu0x02 Clourse 類
證明閉包只是 Clourse 類對象
<?php
$clourse = function () {
echo 'hello clourse';
};
if (is_object($clourse)) {
echo get_class($clourse);
}
// 輸出 Closure上面的代碼將輸出 Closure 證明了閉包只是一個普通的 Closure 類對象。
Clourse 類摘要
我們可以從 PHP 官方手冊 看到閉包類的相關(guān)信息,下面是我在 PhpStorm 的本地文檔查看到 Clourse 類摘要。
/**
* Class used to represent anonymous functions.
* <p>Anonymous functions, implemented in PHP 5.3, yield objects of this type.
* This fact used to be considered an implementation detail, but it can now be relied upon.
* Starting with PHP 5.4, this class has methods that allow further control of the anonymous function after it has been created.
* <p>Besides the methods listed here, this class also has an __invoke method.
* This is for consistency with other classes that implement calling magic, as this method is not used for calling the function.
* @link http://www.php.net/manual/en/class.closure.php
*/
final class Closure {
/**
* This method exists only to disallow instantiation of the Closure class.
* Objects of this class are created in the fashion described on the anonymous functions page.
* @link http://www.php.net/manual/en/closure.construct.php
*/
private function __construct() { }
/**
* This is for consistency with other classes that implement calling magic,
* as this method is not used for calling the function.
* @param mixed $_ [optional]
* @return mixed
* @link http://www.php.net/manual/en/class.closure.php
*/
public function __invoke(...$_) { }
/**
* Duplicates the closure with a new bound object and class scope
* @link http://www.php.net/manual/en/closure.bindto.php
* @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
* @param mixed $newscope The class scope to which associate the closure is to be associated, or 'static' to keep the current one.
* If an object is given, the type of the object will be used instead.
* This determines the visibility of protected and private methods of the bound object.
* @return Closure Returns the newly created Closure object or FALSE on failure
*/
function bindTo($newthis, $newscope = 'static') { }
/**
* This method is a static version of Closure::bindTo().
* See the documentation of that method for more information.
* @static
* @link http://www.php.net/manual/en/closure.bind.php
* @param Closure $closure The anonymous functions to bind.
* @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
* @param mixed $newscope The class scope to which associate the closure is to be associated, or 'static' to keep the current one.
* If an object is given, the type of the object will be used instead.
* This determines the visibility of protected and private methods of the bound object.
* @return Closure Returns the newly created Closure object or FALSE on failure
*/
static function bind(Closure $closure, $newthis, $newscope = 'static') { }
/**
* Temporarily binds the closure to newthis, and calls it with any given parameters.
* @link http://php.net/manual/en/closure.call.php
* @param object $newThis The object to bind the closure to for the duration of the call.
* @param mixed $parameters [optional] Zero or more parameters, which will be given as parameters to the closure.
* @return mixed
* @since 7.0
*/
function call ($newThis, ...$parameters) {}
/**
* @param callable $callable
* @return Closure
* @since 7.1
*/
public static function fromCallable (callable $callable) {}
}首先 Clourse 類為 final 類,也就是說它將無法被繼承,其次它的構(gòu)造函數(shù) __construct 被設(shè)為 private 即無法通過 new 關(guān)鍵字實例化閉包對象,這兩點保證了閉包只能通過 function (...) use(...) {...} 這種語法實例化 。
為什么閉包可以當作函數(shù)執(zhí)行?
從上面的類摘要中我們看出 Clourse 類實現(xiàn)了 __invoke 方法,在 PHP 官方手冊中對該方法解釋如下:
當嘗試以調(diào)用函數(shù)的方式調(diào)用一個對象時,__invoke() 方法會被自動調(diào)用。
這就是閉包可以被當作函數(shù)執(zhí)行的原因。
綁定指定的$this對象和類作用域
在允許使用閉包路由的框架中(如:Slim),我們可以看見如下寫法:
$app->get('/test', function () {
echo $this->request->getMethod();
});在一個閉包居然能中使用 $this?這個 $this 指向哪個對象?
通過 bindTo 和 bind 方法都能夠?qū)崿F(xiàn)綁定 $this 和類作用域的功能,示例如下:
<?php
class Pandas {
public $num = 1;
}
$pandas = new Pandas();
$add = function () {
echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas);
$newAdd1();
// 輸出 2
$newAdd2 = Closure::bind($add, $pandas);
$newAdd2();
// 輸出 3上面的這段例子將指定對象綁定為閉包的 $this,但是我們并沒有指定類作用域。所以如果將 Pandas 類的 $num 屬性改寫為 protected 或 private 則會拋出一個致命錯誤!
Fatal error: Uncaught Error: Cannot access protected property Pandas::$num
在需要訪問綁定對象的非公開屬性或方法時,我們需要指定類作用域,示例如下:
<?php
class Pandas {
protected $num = 1;
}
$pandas = new Pandas();
$add = function () {
echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas, $pandas);
$newAdd1();
// 輸出 2
$newAdd2 = Closure::bind($add, $pandas, 'Pandas');
$newAdd2();
// 輸出 3這里我們看見 bindTo 和 bind 方法都指定了 $newscope 參數(shù),$newscope 參數(shù)默認為 static 即不改變類作用域。$newscope 參數(shù)接受類名或?qū)ο螅㈤]包的類作用域改為指定的類作用域,此時 Pandas 類的 $num 屬性便能夠被閉包訪問。
一次性綁定 $this 對象和類作用域并執(zhí)行(PHP7)
bindTo 和 bind 方法每次指定新的對象和類作用域時都要將原閉包進行復(fù)制然后返回新的閉包,在需要多次修改綁定對象的情景下便顯得繁瑣,所以 PHP7 提供了一個新的方法 call 它能將閉包臨時的綁定到一個對象中(類作用域同時被修改為該對象所屬的類)并執(zhí)行。示例如下:
<?php
class Pandas {
protected $num = 1;
}
$pandas = new Pandas();
$add = function ($num) {
$this->num += $num;
echo $this->num . PHP_EOL;
};
$add->call($pandas, 5);
// 輸出 6Callable 轉(zhuǎn)為閉包(PHP7.1)
在 PHP7.1 中 Closure 類存在 fromCallable 方法能夠?qū)?callable 類型的值轉(zhuǎn)為閉包,示例如下:
<?php
class Foo
{
protected $num = 1;
public static function hello(string $bar)
{
echo 'hello ' . $bar;
}
}
$hello = Closure::fromCallable(['Foo', 'hello']);
$hello('world');這種寫法還是挺爽的畢竟通過閉包調(diào)用總比用 call_user_func 函數(shù)調(diào)用爽的多^_^。
以上就是“PHP閉包及Clourse類的作用是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章題目:PHP閉包及Clourse類的作用是什么
鏈接URL:http://chinadenli.net/article46/goiheg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、關(guān)鍵詞優(yōu)化、網(wǎng)站排名、網(wǎng)站制作、移動網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)