在您的示例中,调用的返回值func1
是一个函数(更具体地说,是 a Closure
)。您收到的错误是由于 php 无法将此对象转换为字符串。如果要打印闭包返回的值,则需要调用它。
function func1() {
return function () {
return 1;
};
}
$f = func1(); // Create the closure
echo $f(); // Calls the closure
这个例子只是一个返回一个函数的函数,并没有说明是什么使闭包与任何其他第一类函数不同,即闭包可以包含其创建所独有的状态。换句话说,您可以从相同的代码生成函数,但它们可以访问的数据不同。
考虑这个简单的例子:
function multiplier($m) {
return function ($v) use ($m) {
return $v * $m;
};
}
$mult_5 = multiplier(5);
echo $mult_5(5); // prints 25
$mult_10 = multiplier(10);
echo $mult_10(5); // prints 50
同样,这是一个非常微不足道的例子,但它确实展示了一些重要的事情。首先,我们只定义了一个函数,但通过调用这个函数,我们只需在调用时更改参数即可生成两个相似但不同的函数。另外,请考虑每个函数都有自己的“状态”。在我命名的函数的情况下$mult_5
,它知道自己的内部$m
值为5
,并且$m
与函数的值不同$mult_10
。其中每一个的值都被传递给multiplier
函数并且该函数已经完成,但该值仍然存在于返回的函数/闭包中。
还值得注意的是,调用的每个返回值multiplier
都是第一类函数,这意味着您可以编写通用函数(如multiplier
),然后使用它们“即时”生成更具体的函数,更具体的函数适合您程序的当前环境/状态。
如果你熟悉 OOP,上面的例子可以很容易地用 OOP 重写:
class Multiplier {
protected $m;
public function __construct($m) {
$this->m = $m;
}
public function multiply($v) {
return $v * $this->m;
}
}
$mult_5 = new Multiplier(5);
echo $mult_5->multiply(5); // prints 25
$mult_10 = new Multiplier(10);
echo $mult_10->multiply(5); // prints 50
...而且,这是非常主观的,但我更喜欢闭包的更简洁的语法。
或者,您可以使用更通用的函数开始:
function multiplier($a, $b) {
return $a * $b;
}
echo multiplier(5, 5);
echo multiplier(5, 10);
但是使用闭包的好处是您可以隐藏数据(如本例中的乘数)。