В руководстве PHP для анонимных функций (т. Е. Closures) говорится, что:
Анонимные функции в настоящее время реализуются с использованием класса Closure. Это деталь реализации, и не следует полагаться на .
(Акцент мой собственный)
Можно ли проверить переменную так, чтобы тест возвращал истину, только если переменная является Замыкание, без ссылки на класс Closure ?
Другими словами, как я могу переписать следующее так, чтобы это приводило к ошибке, когда $ bar
не является анонимной функцией:
function foo(Closure $bar) { $bar(); }
РЕДАКТИРОВАТЬ: На основе полученных ответов приведен пример теста.
Примечания:
ReflectionFunction :: isClosure ()
кажется почти бесполезным: к тому времени, как вы выполните проверки, необходимые для того, чтобы убедиться, что ReflectionFunction действительно может быть создан (может ' t take a Class, кроме Closure), вы исключили все другие параметры. Код:
/**
* Return true if and only if the passed argument is a Closure.
*/
function testClosure($a) {
// Must be Callback, Labmda, Functor or Closure:
if(!is_callable($a)) return false;
// Elminate Callbacks & Lambdas
if(!is_object($a)) return false;
// Eliminate Functors
//$r = new ReflectionFunction($a); <-- fails if $a is a Functor
//if($r->isClosure()) return true;
return false;
}
Тестовый пример:
//////////// TEST CASE /////////////
class CallBackClass {
function callBackFunc() {
}
}
class Functor {
function __invoke() {
}
}
$functor = new Functor();
$lambda = create_function('', '');
$callback = array('CallBackClass', 'callBackFunc');
$array = array();
$object = new stdClass();
$closure = function() { ; };
echo "Is it a closure? \n";
echo "Closure: " . (testClosure($closure) ? "yes" : "no") . "\n";
echo "Null: " . (testClosure(null) ? "yes" : "no") . "\n";
echo "Array: " . (testClosure($array) ? "yes" : "no") . "\n";
echo "Callback: " . (testClosure($callback) ? "yes" : "no") . "\n";
echo "Labmda: " .(testClosure($lambda) ? "yes" : "no") . "\n";
echo "Invoked Class: " . (testClosure($functor) ? "yes" : "no") . "\n";
echo "StdObj: " . (testClosure($object) ? "yes" : "no") . "\n";
-