Основное различие между ними состоит в том , что closure
это класс и типа .callable
callable
Тип принимает все , что может быть под названием :
var_dump(
is_callable('functionName'),
is_callable([$myClass, 'methodName']),
is_callable(function(){})
);
В случае , если closure
будет только принимать анонимную функцию. Обратите внимание , что в PHP версии 7.1 вы можете преобразовать функции закрытия следующим образом:
Closure::fromCallable('functionName')
.
Пример:
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
}
Так зачем использовать closure
овер callable
?
Строгость , потому что closure
это объект , который имеет некоторые дополнительные методы: 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
Вы не хотели бы вызывать методы для нормальной функции, так как это вызовет фатальные ошибки. Итак, чтобы обойти это, вам придется написать что-то вроде:
if($cb instanceof \Closure){}
Делать эту проверку каждый раз бессмысленно. Поэтому, если вы хотите использовать эти методы, укажите, что аргумент - это closure
. В противном случае просто используйте обычный callback
. Сюда; Ошибка возникает при вызове функции вместо вашего кода, что значительно упрощает диагностику.
На стороне записки:closure
класс не может быть продлен , как его окончательным .
["Foo", "bar"]
forFoo::bar
или[$foo, "bar"]
for$foo->bar
.