PHP Closure(闭包)
类摘要
__construct()
空的构造函数,禁止实例化public static bind (Closure $closure, object $newthis [, mixed $newscope = 'static']):Closure
复制一个闭包,绑定指定的$this
对象和类作用域public BindTo(object $newthis [, mixed $newscope = 'static']):Closure
复制当前闭包对象,绑定指定的$this
对象和类作用域
普通方法与匿名方法
<?php
// 声明方法 func
function func() {
return 'hello world';
}
// 匿名函数
$func = function() {
return 'hello world';
};
// hello world
echo func();
// hello world
echo $func();
闭包的实现
将匿名函数作为参数,实现闭包
如果需要将一个方法作为另一个方法的参数,就需要使用匿名方法来实现,声明的普通方法不能被直接被用来当作参数,对于将匿名函数作为参数传入普通函数中;这就实现了一个简单的闭包:
<?php
function func2(Closure $closure) {
return $closure();
}
// func 是一个方法,不能作为 func2 的参数;
// $func 是一个变量(指向一个匿名函数),可以作为 func2 的参数;
// hello world
echo func2($func);
// 等同于 func2($func);
// hello world
echo func2(function(){
return 'hello world';
});
在函数中定义匿名函数,实现闭包
将匿名函数在普通函数中被定义,并在普通函数中被执行;这也实现了一个简单的闭包:
<?php
function echoStr() {
$func = function($str) {
echo $str;
};
$func('hello world');
}
// hello world
echoStr();
将匿名函数作为返回值,实现闭包
将匿名函数在普通函数中被定义,并作为普通函数的返回值;这也实现了一个简单的闭包:
<?php
function getEchoStrFunc() {
$func = function($str) {
echo $str;
};
return $func;
}
$echoStrFunc = getEchoStrFunc();
// hello world
$echoStrFunc('hello world');
闭包的绑定
<?php
// public static bind (Closure $closure, object $newthis [, mixed $newscope = 'static']):Closure
// bind 是 bindTo 的静态版本
// closure 需要绑定的匿名函数
// newthis 匿名函数绑定到的对象,或者null创建未绑定的闭包
// newscope 想要绑定给闭包的类作用域,或者 static 表示不改变。如果传入一个对象,是使用这个对象的类型名。类作用域用来决定在闭包中$this对象的私有、保持方法的可见性
匿名函数的绑定,访问类的公有成员
<?php
// 定义一个类 User,其有一个 age 属性,默认值为17
class User {
public int $age = 17;
}
// 定义匿名函数 $func3,并在其中使用了 this 关键字
$func3 = function() {
return $this->age + 1;
};
// this 关键字,需要在类中进行使用,如果直接进行调用,将会出现 Fatal error: Uncaught Error: Using $this when not in object context
// echo $func3();
// public static bind (Closure $closure, object $newthis [, mixed $newscope = 'static']):Closure
// $func3 需要绑定到一个类中,才能进行使用
$a = Closure::bind($func3, new User);
// 18
echo $a();
静态匿名函数的绑定,访问类的静态成员
<?php
// 定义一个类 User,其有一个 age 属性,默认值为17;一个 name 属性
class User {
private static $name = 'Jason';
public int $age = 17;
}
$getName = static function() {
return self::$name;
};
// Cannot bind an instance to a static closure
// $b = Closure::bind($getName, new User);
// echo $b();
$b = Closure::bind($getName, null, new User);
// Jason
echo $b();
匿名函数绑定,访问类的私有成员
<?php
// 定义一个类 User,其有一个 age 属性,默认值为17;一个 name 属性,一个 last_name 属性
class User {
private static $name = 'Jason';
public int $age = 17;
private $last_name = 'Zhang';
}
$getLastName = function() {
return $this->last_name;
};
// Fatal error: Uncaught Error: Cannot access private property User::$last_name
// $c = Closure::bind($getLastName, new User);
// echo $c();
$c = Closure::bind($getLastName, new User, 'User');
// Zhang
echo $c();
闭包的动态绑定
<?php
// 定义一个实现动态绑定的 trait
trait DynamicFunc {
public function __call($name, $args) {
if (is_callable($this->$name)) {
return call_user_func($this->$name, $args);
} else {
throw new \Exception('Method ' . $name . ' does not exists.');
}
}
public function __set($name, $value) {
// bindTo($this) 只能访问公有属性
// bindTo($this, $this) 访问私有属性
$this->$name = is_callable($value) ? $value->bindTo($this, $this) : $value;
}
}
// 定义一个类 User,其有一个 age 属性,默认值为17;一个 name 属性,一个 last_name 属性;通过 use 引入 trait DynamicFunc
class User {
use DynamicFunc;
private static $name = 'Jason';
public int $age = 17;
private $last_name = 'Zhang';
}
$user = new User();
// 通过调用 __set 给实例添加 getLastName 方法
$user->getLastName = function() {
return $this->last_name;
};
// Zhang
echo $user->getLastName();