Обычно в PHP, если у вас есть метод bar
класса Foo
и вы хотели бы передать его как вызываемый, вы используете что-то вроде
$foo = new Foo();
$callable = [$foo, 'bar'];
Недостатком этого является то, что is_array($callable)
оценивает true
,
Есть ли другой возможный способ передать метод класса как вызываемый так, чтобы is_array($callable)
возвращается false
?
Да, есть … хотя это ужасный, ужасный хак
$foo = new Foo();
function makeCallable($instance, $method)
{
return function() use ($instance, $method) {
return $instance->{$method}();//use func_get_args + call_user_func_array to support arguments
};
}
Тогда вы можете использовать:
$callable = makeCallable($foo, 'bar');
var_dump(is_array($callable));//false
Недостатком является то, что:
var_dump($callbale instanceof Closure);//true
По сути, не обращайте внимания на тот факт, что ваш вызываемый объект также является массивом, а просто используйте подсказки типов во всей базе кода:
function foobar(callable $action)
{
return call_user_func($action);
}
Это должно работать просто отлично.
От того, почему вы чувствуете, что текущий вызываемый массив является недостатком: я понимаю, почему вы чувствуете, что это не очень хорошая вещь. Никто не должен знать, что конкретная вызываемая конструкция — это массив, или строка, или анонимная функция (которая на самом деле является экземпляром Closure
класс — еще одна деталь реализации, которую вы, возможно, не захотите передавать). Но это именно потому, что вызываемые конструкции бывают разных форм, callable
подсказка типа существует: код, который вы пишете, который требует вызываемого объекта, не должен заботиться о том, как реализован этот вызываемый объект, ему просто нужно знать, что он может вызвать эту часть информации:
function handleEvent(callable $action, array $args = null)
{
if ($args) {
return call_user_func_array($action, $args);
}
return call_user_fun($action);
}
Мне не нужно проверять, если $action
это строка (как 'strtolower'
, Closure
экземпляр или массив) я просто знать Я могу назвать это
Функции и методы не первоклассные граждане в PHP, т.е. они не могут быть назначены переменной, не имеют типа и т. д.
callable
на самом деле не тип, is_callable
так же хорошо как callable
подсказка типа просто проверяет, может ли быть что-то используется как функция. Это может быть:
[class, method]
для статического метода[object, method]
для метода экземпляраClosure
пример__invoke()
Как видите, все эти значения на самом деле имеют другой тип и просто могут быть вызваны. Не существует такого понятия, как «чистый» вызов, который не имеет другого типа.