PHP:类型提示 - `Closure` 和 `Callable` 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29730720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP: Type hinting - Difference between `Closure` and `Callable`
提问by Dev01
I noticed that I can use either of Closure
or Callable
as type hint if we expected some callback function to run. For example:
我注意到如果我们希望运行一些回调函数,我可以使用 ofClosure
或Callable
as 类型提示。例如:
function callFunc1(Closure $closure) {
$closure();
}
function callFunc2(Callable $callback) {
$callback();
}
$function = function() {
echo 'Hello, World!';
};
callFunc1($function); // Hello, World!
callFunc2($function); // Hello, World!
Question:
题:
What's the difference here ? In other words when to use Closure
and when to use Callable
OR they serve the same purpose ?
这里有什么区别?换句话说,何时使用Closure
和何时使用Callable
OR 它们具有相同的目的?
回答by Rizier123
The difference is, that a Closure
must be an anonymous function, where callable
also can be a normal function.
不同的是,aClosure
必须是匿名函数, wherecallable
也可以是普通函数。
You can see/test this with the example below and you will see that you will get an error for the first one:
您可以使用下面的示例查看/测试它,您将看到第一个错误:
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!
So if you only want to type hint anonymous function use: Closure
and if you want also to allow normal functions use callable
as type hint.
因此,如果您只想键入提示匿名函数,请使用:Closure
如果您还想允许普通函数callable
用作类型提示。
回答by Xorifelse
The main difference between them is that a closure
is a classand callable
a type.
它们之间的主要区别在于 aclosure
是一个类和callable
一个类型。
The callable
type accepts anything that can be called:
该callable
类型接受可以调用的任何内容:
var_dump(
is_callable('functionName'),
is_callable([$myClass, 'methodName']),
is_callable(function(){})
);
Where a closure
will onlyaccept an anonymous function. Note that in PHP version 7.1 you can convert functions to a closure like so:
Closure::fromCallable('functionName')
.
凡closure
将只接受了一个匿名函数。请注意,在PHP 7.1版,您可以函数转换为封闭,像这样:
Closure::fromCallable('functionName')
。
Example:
例子:
namespace foo{
class bar{
private $val = 10;
function myCallable(callable $cb){$cb()}
function myClosure(\Closure $cb){$cb()} // type hint must refer to global namespace
}
function func(){}
$cb = function(){};
$fb = new bar;
$fb->myCallable(function(){});
$fb->myCallable($cb);
$fb->myCallable('func');
$fb->myClosure(function(){});
$fb->myClosure($cb);
$fb->myClosure(\Closure::fromCallable('func'));
$fb->myClosure('func'); # TypeError
}
So why use a closure
over callable
?
那么为什么要使用closure
overcallable
呢?
Strictness because a closure
is an object that has some additional methods: call()
, bind()
and bindto()
. They allow you to use a function declared outside of a class and execute it as if it was inside a class.
严格是因为 aclosure
是一个对象,它有一些额外的方法:call()
,bind()
和bindto()
。它们允许您使用在类外部声明的函数并像在类内部一样执行它。
$inject = function($i){return $this->val * $i;};
$cb1 = Closure::bind($inject, $fb);
$cb2 = $inject->bindTo($fb);
echo $cb1->call($fb, 2); // 20
echo $cb2(3); // 30
You would not like to call methods on a normal function as that will raise fatal errors. So in order to circumvent that you would have to write something like:
您不希望在正常函数上调用方法,因为这会引发致命错误。因此,为了避免这种情况,您必须编写如下内容:
if($cb instanceof \Closure){}
To do this check every time is pointless. So if you want to use those methods state that the argument is a closure
. Otherwise just use a normal callback
. This way; An error is raised on function call instead of your code causing it making it much easier to diagnose.
每次都做这个检查是没有意义的。因此,如果您想使用这些方法,请声明参数是closure
. 否则只需使用正常的callback
. 这边走; 在函数调用而不是您的代码上引发错误,导致它更容易诊断。
On a side note:The closure
class cannot be extended as its final.
在一个侧面说明:本closure
类不能扩展为最终。
回答by Rod Elias
It's worth mentioning that this won't work for PHP versions 5.3.21 to 5.3.29.
值得一提的是,这不适用于 PHP 版本 5.3.21 到 5.3.29。
In any of those versions you will get an output like:
在这些版本中的任何一个中,您都会得到如下输出:
Hello, World! Catchable fatal error: Argument 1 passed to callFunc2() must be an instance of > Callable, instance of Closure given, called in /in/kqeYD on line 16 and defined in /in/kqeYD on line 7
Process exited with code 255.
你好,世界!可捕获的致命错误:传递给 callFunc2() 的参数 1 必须是 > Callable 的实例,给定的闭包实例,在第 16 行的 /in/kqeYD 中调用并在第 7 行的 /in/kqeYD 中定义
进程退出,代码为 255。
One can try that out using https://3v4l.org/kqeYD#v5321
可以使用https://3v4l.org/kqeYD#v5321尝试一下
Best regards,
此致,