Основна відмінність між ними полягає в тому , що 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){}
Робити цю перевірку кожен раз безглуздо. Тож якщо ви хочете скористатися цими методами, зазначайте, що аргументом є a closure. В іншому випадку просто використовуйте звичайне callback. Сюди; Під час виклику функції виникає помилка замість коду, що робить його набагато простіше діагностувати.
На стороні записки:closure клас не може бути продовжений , як його остаточним .
["Foo", "bar"]дляFoo::barабо[$foo, "bar"]для$foo->bar.