Тестирование на закрытие PHP без обращения к внутреннему классу Closure

В руководстве PHP для анонимных функций (т. Е. Closures) говорится, что:

Анонимные функции в настоящее время реализуются с использованием класса Closure. Это деталь реализации, и не следует полагаться на .

(Акцент мой собственный)

Можно ли проверить переменную так, чтобы тест возвращал истину, только если переменная является Замыкание, без ссылки на класс Closure ?

Другими словами, как я могу переписать следующее так, чтобы это приводило к ошибке, когда $ bar не является анонимной функцией:

function foo(Closure $bar) {
    $bar();
}

РЕДАКТИРОВАТЬ: На основе полученных ответов приведен пример теста.

Примечания:

  1. Кажется, нет способа различать функторы и замыкания, и что этот тест, вероятно, так же «специфичен для реализации», как и использование класса Closure.
  2. (на первый взгляд очевидный) метод ReflectionFunction :: isClosure () кажется почти бесполезным: к тому времени, как вы выполните проверки, необходимые для того, чтобы убедиться, что ReflectionFunction действительно может быть создан (может ' t take a Class, кроме Closure), вы исключили все другие параметры.
  3. В версии 5.3.0 ReflectionClass ($ closure) -> hasMethod ('__ invoke') возвращал false, так что это можно использовать в качестве теста против Функторов, однако (как мне сказали) с тех пор это изменилось. Это также подчеркивает хрупкость решения.
  4. Продолжение Gordon - Начиная с PHP 5.4 вы можете полагаться на то, что закрытие является закрытием: php.net/manual/en/class.closure .php

Код:

/**
 * 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";

-

9
задан Community 23 May 2017 в 11:53
поделиться