それらの間の主な違いは、ということでclosure
あるクラスやタイプ。callable
callable
タイプは何もすることができ受け入れると呼ばれるが。
var_dump(
is_callable('functionName'),
is_callable([$myClass, 'methodName']),
is_callable(function(){})
);
ここで、a 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
overを使用するの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
クラスをfinalとして拡張することはできません。
["Foo", "bar"]
forFoo::bar
または[$foo, "bar"]
for などの配列を渡すことにより、callableでクラスメソッドを使用することもでき$foo->bar
ます。