PHP:types提示 – “Closure”和“Callable”之间的区别

我注意到,如果我们期望一些callback函数运行,我可以使用ClosureCallable作为types提示。 例如:

 function callFunc1(Closure $closure) { $closure(); } function callFunc2(Callable $callback) { $callback(); } $function = function() { echo 'Hello, World!'; }; callFunc1($function); // Hello, World! callFunc2($function); // Hello, World! 

题:

这里有什么区别? 换句话说,何时使用Closure以及何时使用Callable OR,它们的用途是相同的?

不同的是, Closure必须是一个匿名函数, callable也可以是一个正常的函数。

你可以用下面的例子看看/testing这个,你会看到第一个错误:

 function callFunc1(Closure $closure) { $closure(); } function callFunc2(Callable $callback) { $callback(); } function xy() { echo 'Hello, World!'; } callFunc1("xy"); // Catchable fatal error: Argument 1 passed to callFunc1() must be an instance of Closure, string given callFunc2("xy"); // Hello, World! 

所以,如果你只想键入提示匿名函数使用: Closure ,如果你还想让正常的function使用callable的types提示。

它们之间的主要区别是closure是一个callable是一种types 。 很容易忘记这一点,因为closure是一个特殊的类,它并不真正作为其他类初始化。

callabletypes接受任何可以callable东西:

  1. call_user_func('my_functionName')
  2. call_user_func('MyClass::myStaticMethodName')
  3. call_user_func([new MyClass, 'myMethodName'])
  4. call_user_func(function(){})

closure只接受后者(上述#4) 。 自PHP 7.1以来。 但是你可以使用Closure::fromCallable('my_functionName')将任何函数转换为闭Closure::fromCallable('my_functionName')

 namespace foo{ class bar{ private $val = 10; // this value will be used in later example code. function a(callable $cb){$cb()} function b(\closure $cb){$cb()} // type hint must refer to global namespace } } 

使用下面的代码来testing:

 function func(){} $cb = function(){}; $fb = new foo\bar; $fb->a(function(){}); $fb->a($cb); $fb->a('func'); $fb->b(function(){}); $fb->b($cb); $fb->b('func'); # TypeError 

那么为什么使用callableclosure呢? 那么请记住, closure是一个具有一些附加方法的对象: bind()bindto()call() 。 它们允许您使用在类之外声明的函数,并像在类中一样执行它。

 $cb1 = function($i){return $this->val * $i;}; $cb2 = Closure::bind($cb1, $fb); $cb3 = $cb1->bindTo($fb); $cbi = (function($i){return $this->val * $i;})->bindTo($fb); // inline, same as $cb3. echo $cb1->call($fb, 2); // 20 echo $cb2(3); // 30 echo $cb3(4); // 40 

在旁注: closure类不能作为其最终的扩展。

值得一提的是,这不适用于PHP版本5.3.21至5.3.29。

在这些版本的任何一个,你会得到一个输出:

你好,世界! 可捕获的致命错误:传递给callFunc2()的参数1必须是> Callable的实例,给出的Closure实例,在第16行的/ in / kqeYD中调用,并在第7行的/ in / kqeYD中定义

用代码255退出进程。

可以使用https://3v4l.org/kqeYD#v5321来尝试一下;

最好的祝福,