这是代码,它是一个简单的容器。
class Application
{
private $recipes;
private $instances;
public function configureCache(XXXXXXXX $closure) {
$recipes['cache'] = $closure;
}
public function getCache(): Cache {
if (empty($instances['cache'])) {
$instances['cache'] = $recipes['cache']();
}
return $instances['cache'];
}
}
此代码在PHP 7.1+上运行。我可以为XXXXXXXX填写哪些内容以使其最具体?类型是一个函数,更具体地说是一个返回Cache的函数。
答案 0 :(得分:7)
PHP支持几种可调用实体的语法:包含函数名的字符串,对象和方法的数组,静态方法的类和方法数组,第一类闭包和生成的闭包。
所有这些的类型提示是callable
。
如果只想要匿名函数,即第一类闭包,请使用Closure
。但这会限制你可以接受的可赎回种类。
截至目前,PHP不支持关于形式可调参数的参数提示或返回类型提示:例如,您的代码不能说只接受带有一个字符串参数并返回布尔值的闭包。
答案 1 :(得分:0)
如果您特别想强迫某人传递匿名函数,那么它将始终是the Closure class的实例。
如果你真正想要的是“你可以像函数一样使用的东西”,你可以使用callable pseudo-type,它接受闭包和各种字符串和数组符号来引用命名函数和方法。
您还可以使用Closure::fromCallable将任何可调用对象转换为Closure实例。
不幸的是,你不能得到更具体的东西;有提议暗示特定的callables签名,或允许他们满足特制的接口定义,但尚未采用任何一个。
但是,您可以要求一个对象使用一个方法实现普通接口,我相信该方法可以是the magic __invoke method。然后,调用者可以使用anonymous class而不是匿名函数:
interface CacheFactory {
public function __invoke(): Cache;
}
$app->configureCache(new class implements CacheFactory {
public function __invoke(): Cache {
return new Cache;
}
});
请注意,生成的对象本身会传递callable
类型提示以及CacheFactory
,并且可以像示例中的匿名函数一样使用。
但是,即使使用此解决方案,只在运行时检查类型,因此此代码本身不会引发任何错误,并且您将在10%的时间内收到类型错误< em>当你实际运行回调时:
$app->configureCache(new class implements CacheFactory {
public function __invoke(): Cache {
return rand(0,10) > 9 ? "Nonsense" : new Cache;
}
});
大多数情况下,您可能只想要callable
和一些好的文档。