<!-- TOC -->php
<!-- /TOC -->閉包
有收穫的話請加顆小星星,沒有收穫的話能夠 反對 沒有幫助 舉報三連函數
匿名函數(Anonymous functions),也叫閉包函數(closures),容許 臨時建立一個沒有指定名稱的函數。最常常用做回調函數(callback)參數的值。固然,也有其它應用的狀況。測試
匿名函數目前是經過 Closure 類來實現的。ui
$rs = preg_replace_callback('/-([a-z])/', function ($match) { return strtoupper($match[1]); }, 'hello-world'); dump($rs); // "helloWorld"
$greet = function ($name) { dump($name); }; dump($greet instanceof Closure); // true $greet('PHP'); // "PHP"
$message = 'hello'; $example = function () use ($message) { dump($message); }; dump($example instanceof Closure); // true $example(); // "hello"
call_user_func_array()
和call_user_func()
方法function call_user_func ($function, ...$parameter) {}this
該方法接收多個參數,第一個就是回調函數,能夠是普通函數
,也能夠是閉包函數
,後面的多個參數
都是做爲函數回調使用spa
$rs = call_user_func(function (...$params) { return func_get_args(); }, 1, 2, 3); dump($rs); // [1,2,3]
function call_user_func_array ($function, array $param_arr) {}
該方法接收2個參數,第一個就是回調函數,能夠是普通函數
,也能夠是閉包函數
,後面的數組參數
都是做爲函數回調使用
$rs = call_user_func_array(function (array $params) { return func_get_args(); }, [1, 2, 3]); dump($rs); // [1,2,3]
樓主看法是將方法綁定到指定類上,使得方法也可使用類的屬性和方法,很是適合配合__call()
魔術方法和call_user_func_array
方法一塊兒使用
function bindTo($newthis, $newscope = 'static') { }
<?php namespace PHP\Demo\Closure; class ClosureBindTo { public function __call($name, $arguments) { if (count($arguments) > 1 && $arguments[0] instanceof \Closure) { return call_user_func_array($arguments[0]->bindTo($this), array_slice($arguments, 1)); } throw new \InvalidArgumentException("沒有這個方法"); } } // 測試 public function testClosureBindTo() { $obj = new ClosureBindTo(); $this->assertEquals(2, $obj->add(function (array $params) { return ++$params[0]; }, [1])); // 測試同一個實例 $newObj = $obj->test(function (array $params){ return $this; }, [1]); $this->assertTrue($newObj instanceof $obj); }
static function bind(Closure $closure, $newthis, $newscope = 'static') { }
bind函數是bindTo的靜態表示
<?php namespace PHP\Demo\Closure; class ClosureBind { private $methods = []; public function addMethod(string $name, \Closure $callback) { if (!is_callable($callback)) { throw new \InvalidArgumentException("第二個參數有誤"); } $this->methods[$name] = \Closure::bind($callback, $this, get_class()); } public function __call(string $name, array $arguments) { if (isset($this->methods[$name])) { return call_user_func_array($this->methods[$name], $arguments); } throw new \RuntimeException("不存在方法[{$name}]"); } } // 測試 public function testClosureBind() { $obj = new ClosureBind(); $obj->addMethod('add', function (array $params) { return ++$params[0]; }); $this->assertEquals(2, $obj->add([1])); // 測試同一個實例 $obj->addMethod('test', function (array $params) { return $this; }); $this->assertTrue($obj->test([1]) instanceof $obj); }