通常在PHP中,如果你有一个类$departments = Get-ADUser -Filter * -Property Department |
Where-Object { $_.Department } |
Select -Expand Department -Unique
$departments | Out-File 'H:\TEST\DEPTAAAAA.csv'
的方法a = 1
f = fn
new_a when a === new_a -> true
_ -> false
end
并且你想将它传递给一个可调用的,你可以使用像
bar
这样做的缺点是Foo
评估为$foo = new Foo();
$callable = [$foo, 'bar'];
。
是否有另一种可行的方法可以将类方法作为可调用方传递,以便is_array($callable)
返回true
?
答案 0 :(得分:10)
是的,有......虽然这是一个可怕的,可怕的黑客:
$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
基本上,不要注意你的callable也是一个数组,只需在整个代码库中使用type-hinting:
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
实例或数组)我只是知道我可以调用它
答案 1 :(得分:4)
PHP中的函数和方法不是一等公民,即它们不能分配给变量,没有类型等。
callable
实际上并不是一种类型,is_callable
以及callable
类型提示只是检查某些内容是否可以用作函数 。这可以是:
[class, method]
[object, method]
Closure
实例__invoke()
如您所见,所有这些值实际上都有不同的类型,恰好可以"可调用"。没有"纯粹的"可调用的,没有其他类型。
答案 2 :(得分:1)
PHP 7.1最终通过Closure :: fromCallable(RFC)使回调成为一等公民。
如here所述,您可以像这样使用它:
class MyClass
{
public function getCallback() {
return Closure::fromCallable([$this, 'callback']);
}
public function callback($value) {
echo $value . PHP_EOL;
}
}
$callback = (new MyClass)->getCallback();
$callback('Hello World');
使用它有一些好处:
更好的错误处理-使用Closure :: fromCallable时,它在正确的位置显示错误,而不是在我们使用可调用的位置显示错误。这使调试容易得多。
包装范围-即使回调是MyClass的私有/受保护方法,上面的示例也可以正常工作。
性能-通过避免检查给定可调用项是否确实是可调用项的开销,这也可以提高性能。