0%

PHP中匿名函数

匿名函数,说白了就是”没有名字的函数”

1
2
3
$foo = function(){
//this is a closure;
}

上面声明的就是匿名函数,没有什么特别的,和一般函数结构神似,唯独少了个函数名。并且这个函数可以作为一个值被赋予一个变量或者对象属性。这种特性是的拥有匿名函数的编程语言在设计一些应用时,更为灵活。

匿名函数和普通函数最大的区别是在于:

  1. 匿名函数可以作为一个具体的”值”赋予给变量或者对象属性
  2. 匿名函数可以被定义在不同地方,使得它可以有效利用他所在的局域内的变量(或者说上下文环境)
1
2
3
4
5
6
7
8
9
10
11
class foo
{
public function exec(Closure $callback)
{
echo $callback();//hi ,nick
}
}
$name = "nick";
(new foo())->exec(function() use ($name){
return "hi ,".$name;
});

可以看到,匿名函数使用使用了上下文中的变量$name。而实际上,这个匿名函数实在另一个地方被执行(foo类里面)。这样使得我们不必将变量$name的值通过参数传递到foo类的exec方法中,而且可以减少在exec方法中不必要的处理逻辑,使得类跟家专注于自己的职责;

匿名函数定义时不会被执行,除非被调用,上文中的例子就是这样,利用这种特性,我们可以利用它来实现一个控制反转(IoC)容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* 一个简单的IoC容器
*/
class Container
{
protected static $bindings;

public static function bind($abstract, Closure $concrete)
{
static::$bindings[$abstract] = $concrete;
}

public static function make($abstract)
{
return call_user_func(static::$bindings[$abstract]);
}
}

/**
* 示例用的 talk 类
*/
class talk
{
public function greet($target)
{
echo 'hi, ' . $target->getName();
}
}

/**
* 示例用的 A 类
*/
class A
{
public function getName()
{
return 'Nick';
}
}

/**
* 示例用的 B 类
*/
class B
{
public function getName()
{
return 'Amy';
}
}

// 以下代码是主要示例代码

// 创建一个talk类的实例
$talk = new talk;

// 将A类绑定至容器,命名为foo
Container::bind('foo', function() {
return new A;
});

// 将B类绑定至容器,命名为bar
Container::bind('bar', function() {
return new B;
});

// 通过容器取出实例
$talk->greet(Container::make('foo')); // hi, Nick
$talk->greet(Container::make('bar')); // hi, Amy

上述例子中,只有通过make方法获取实例的时候,实例才被创建,使得我们可以实现容器。