Closure::bind && Closure::bindTo

Closure::bind

Closure::bind — 複製一個閉包,綁定指定的$this對象和類做用域。php

其實後半句表述很不清楚。 個人理解: 把一個閉包轉換爲某個類的方法(只是這個方法不須要經過對象調用), 這樣閉包中的$this、static、self就轉換成了對應的對象或類。閉包

建立並返回一個 匿名函數, 它與當前對象的函數體相同、綁定了一樣變量,但能夠綁定不一樣的對象,也能夠綁定新的類做用域。函數

從我我的理解,和js裏面的call函數有點相似。能夠改變閉包對象指定的做用域。this

簡單說,就是把閉包當成對象的成員方法或者靜態成員方法.code

這個方法是 Closure::bindTo() 的靜態版本對象

說明

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

參數

  • closure作用域

    須要綁定的匿名函數。文檔

  • newthisget

    須要綁定到匿名函數的對象,或者 NULL 建立未綁定的閉包。io

  • newscope

    想要綁定給閉包的類做用域,或者 'static' 表示不改變。若是傳入一個對象,則使用這個對象的類型名。 類做用域用來決定在閉包中 $this 對象的 私有、保護方法 的可見性

返回值

返回一個新的 Closure 對象 或者在失敗時返回 FALSE

理解

範例

class A {
    private static $sfoo = 1;
    private $ifoo = 2;
}
$cl1 = static function() {
    return A::$sfoo;
};
$cl2 = function() {
    return $this->ifoo;
};

$bcl1 = Closure::bind($cl1, null, 'A');  //就至關於在類裏面加了個靜態成員方法
$bcl2 = Closure::bind($cl2, new A(), 'A');  //至關於在類裏面加了個成員方法
echo $bcl1(), "\n";
echo $bcl2(), "\n";

成員方法中使用$this訪問對象, 靜態成員方法直接使用類名::成員的方法。

可是由於返回的是匿名函數, 沒有函數名, 因此返回一個已經綁定$this對象和類做用域的閉包給你使用.

返回的閉包函數,已經綁定了$this對象和類的做用域,意思就是說直接執行閉包函數,就是至關於執行的是對象方法,或者類方法

講解幾種狀況

  • 一、只綁定$this對象.
  • 二、只綁定類做用域.
  • 三、同時綁定$this對象和類做用域.(文檔的說法)
  • 四、都不綁定.(這樣一來只是純粹的複製, 文檔說法是使用cloning代替bind或bindTo)

1.只綁定$this對象

closure = function ($name, $age) {
    $this->name = $name;
    $this->age = $age;
};

class Person {
    public $name;
    public $age;

    public function say() {
        echo "My name is {$this->name}, I'm {$this->age} years old.\n";
    }
}

$person = new Person();

//把$closure中的$this綁定爲$person
//這樣在$bound_closure中設置name和age的時候其實是設置$person的name和age
//也就是綁定了指定的$this對象($person)
$bound_closure = Closure::bind($closure, $person);
 
$bound_closure('php', 100);
$person->say(); //輸出:My name is php, I’m 100 years old.

注意: 在上面的這個例子中,是不能夠在$closure中使用static的,若是須要使用static,經過第三個參數傳入帶命名空間的類名。

把closure閉包函數中的 $this 綁定到一個對象,這樣執行閉包函數,就至關於執行對象的方法。

至關於就是在對象中添加了成員方法,因此閉包函數內的處理也就在處理對象內數據

二、只綁定類做用域.

$closure = function ($name, $age) {
  static::$name =  $name;
  static::$age = $age;
};
 
class Person {
    static $name;
    static $age;
 
    public static function say()
    {
        echo "My name is " . static::$name . ", I'm " . static::$age. " years old.\n";
    }
}
 
//把$closure中的static綁定爲Person類
//這樣在$bound_closure中設置name和age的時候其實是設置Person的name和age
//也就是綁定了指定的static(Person)
$bound_closure = Closure::bind($closure, null, Person::class);
  
$bound_closure('php', 100);
 
Person::say(); //輸出:My name is php, I’m 100 years old.

注意: 在上面的例子中,是不能夠在$closure中使用$this的,由於咱們的bind只綁定了類名,也就是static,若是須要使用$this,新建一個對象做爲bind的第二個參數傳入。

三、同時綁定$this對象和類做用域.(文檔的說法)

在這個例子中能夠在$closure中同時使用$this和static

$closure = function ($name, $age, $sex) {
    $this->name = $name;
    $this->age = $age;
    static::$sex = $sex;
};
 
class Person {
    public $name;
    public $age;
 
    static $sex;
 
    public function say()
    {
        echo "My name is {$this->name}, I'm {$this->age} years old.\n";
        echo "Sex: " . static::$sex . ".\n";
    }
}
 
$person = new Person();
 
//把$closure中的static綁定爲Person類, $this綁定爲$person對象
$bound_closure = Closure::bind($closure, $person, Person::class);
$bound_closure('php', 100, 'female');
 
$person->say(); //輸出:My name is php, I’m 100 years old. Sex: female.

四、都不綁定.(這樣一來只是純粹的複製, 文檔說法是使用cloning代替bind或bindTo)

$closure = function () {
    echo "bind nothing.\n";
};
 
//與$bound_closure = clone $closure;的效果同樣
$bound_closure = Closure::bind($closure, null);
 
$bound_closure();//輸出:bind nothing.

這個就用clone好了吧…

Closure::bindTo

Closure::bindTo — 複製當前閉包對象,綁定指定的$this對象和類做用域。

建立並返回一個 匿名函數, 它與當前對象的函數體相同、綁定了一樣變量,但能夠綁定不一樣的對象,也能夠綁定新的類做用域。

「綁定的對象」決定了函數體中的 $this 的取值,「類做用域」表明一個類型、決定在這個匿名函數中可以調用哪些 私有 和 保護 的方法。 也就是說,此時 $this 能夠調用的方法,與 newscope 類的成員函數是相同的。

靜態閉包不能有綁定的對象( newthis 參數的值應該設爲 NULL)不過仍然能夠用 bubdTo 方法來改變它們的類做用域。

說明

public Closure::bindTo ( object $newthis [, mixed $newscope = 'static' ] ) : Closure``

參數

  • newthis

    綁定給匿名函數的一個對象,或者 NULL 來取消綁定。

  • newscope

    關聯到匿名函數的類做用域,或者 'static' 保持當前狀態。若是是一個對象,則使用這個對象的類型爲心得類做用域。 這會決定綁定的對象的 保護、私有成員 方法的可見性。

返回值

返回新建立的 Closure 對象 或者在失敗時返回 FALSE

若是你只是想要複製一個匿名函數,能夠用 cloning 代替。

例子

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";

和 Closure::bind() 做用同樣,只是一個是靜態的調用,一個是對象的的調用。

對比 Closure::bind 和 Closure::bindTo

二者功能功能同樣,不一樣的是匿名函數的來源不同,Closure::bind 是靜態調用,直接是閉包函數當參數傳入;而Closure::bindTo是對象方式調用,閉包函數是從另一個對象中獲取的,而後在綁定到其餘對象上。

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息