PHP 閉包及Closure類

匿名函數

實現一個簡單的匿名函數:php

$func = function() {

    echo "this is a func\n";

};

上面就是一個簡單的匿名函數,定義一個函數體,將函數體賦值給一個變量(php5.3以後支持該寫法)。golang

實現閉包

一、當作參數傳遞:
<?php

// 定義一個匿名函數,賦值給$func

$func = function($param) {

    var_dump($param);

};

// 將匿名函數做爲參數傳入,並調用該參數

function dFunc($func, $param) {

    $func($param);

}

dFunc($func, '123'); // 輸出:string(3) "123"
二、將匿名函數返回:
<?php

// 定義一個函數,在該函數中將內部的匿名函數返回

function cFunc($param) {

    $func = function($param1) use ($param) {

    echo "params:".$param1." ".$param;

};

return $func;

}

// 獲取並調用匿名函數

$rCFunc = cFunc("123");

$rCFunc("456"); // params:456 123

捕獲外界變量

閉包: 閉包是詞法做用於的體現,一個持有外部環境自由變量的函數就是閉包。閉包體現的是在程序運行過程當中,由 「不肯定」變爲「 肯定」 的過程。

捕獲外部變量: 在PHP中對捕獲這一動做有了更清晰的表現,使用use關鍵字。如上面例2。閉包

在上面的例2中,匿名函數$func經過use關鍵字捕獲了外部的自由變量$param,在調用時經過傳入cFunc()函數的參數123($param此時會變爲「肯定」狀態),進而調用匿名函數時輸出「params:456 123」。函數

use引入的是自由變量的副本。this

例如:

<?php

/*

輸出結果:

匿名函數執行前:p1:p1

匿名函數內修改後:p1:p2

匿名函數執行完:p1:p1

*/

function f1() {

    $p1 = "p1";

    echo "匿名函數執行前:p1:$p1\n";

    $func = function() use ($p1) {

        $p1 = "p2";

        echo "匿名函數內修改後:p1:$p1\n";

    };

$func();

echo "匿名函數執行完:p1:$p1\n";

}

f1();
golang閉包: 在golang中一樣經過匿名函數實現了閉包,和PHP不一樣的是,golang中的閉包是默認會引入上下文的自由變量,且引入的地址,即在閉包函數內部修改變量會在函數外部生效。

PHP Closure類

用於表明匿名函數類。在PHP中定義一個閉包函數其實就是一個Closure類的實例。
<?php

/*

輸出:

object(Closure)#1 (0) {

}

*/

$func = function() {};

    var_dump($func);
類摘要
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對象和類做用域。

Closure::bind

複製一個閉包,綁定指定的$this對象和類做用域,返回一個新的匿名函數code

參數說明:對象

  • closure: 須要綁定的匿名函數。
  • newthis: 須要綁定到匿名函數的對象,或者 NULL 建立未綁定的閉包。(理解:能夠選擇是否將匿名函數綁定到一個類對象,若綁定到了一個類對象,則能夠在匿名函數內使用$this,不然不可以使用。
  • newscope: 想要綁定給閉包的類做用域,或者 'static' 表示不改變。若是傳入一個對象,則使用這個對象的類型名。 類做用域用來決定在閉包中 $this 對象的 私有、保護方法 的可見性。(理解:若是傳入一個類,則能夠訪問類的static、private、protected屬性,不然只能訪問public屬性。

簡單理解:能夠簡單理解爲將該匿名函數綁定到一個類或實例。根據參數的不一樣,能夠訪問不一樣的類的屬性。作用域

<?php

class A{

    private static $_cat = 'cat';

    private $_dog = 'dog';

    public $pig = 'pig';

}

$cat = static function() {

    var_dump(A::$_cat);

};

$dog = function() {

    var_dump($this->_dog);

};

$pig = function() {

    var_dump($this->pig);

};

// 傳入null,不可以使用$this,但傳入A類,則能夠訪問static等

$bindCat = Closure::bind($cat, null, 'A');

echo "bind cat\n";

$bindCat();

// 傳入new A()對象,A類,可使用$this訪問私有屬性。

$bindDog = Closure::bind($dog, new A(), 'A');

echo "bind dog\n";

$bindDog();

// 爲傳入類對象,不可以使用$this

$bindDog2 = Closure::bind($dog, null, 'A');

echo "bind dog2\n";

$bindDog2();
輸出:
bind cat
string(3) "cat"
bind dog
string(3) "dog"
bind dog2
Fatal error: Using $this when not in object context

Closure::bindTo

Closure::bind()的非靜態形式。string

小結

  • PHP經過匿名函數實現閉包。
  • 能夠經過將匿名函數做爲參數或返回值實現閉包。
  • 能夠經過use關鍵字引入外部變量,且引入的變量副本。
  • 匿名函數均實現了Closure類,且能夠經過Closure::bind()方法將匿名函數綁定到某個類。
相關文章
相關標籤/搜索