旧帖子但可变参数函数和数组解包可用于(有一些限制)来完成类型化数组提示,至少在 PHP7 中是这样。 (我没有在早期版本上进行测试)。
示例:
class Foo {
public function test(){
echo "foo";
}
};
class Bar extends Foo {
//override parent method
public function test(){
echo "bar";
}
}
function test(Foo ...$params){
foreach($params as $param){
$param->test();
}
}
$f = new Foo();
$b = new Bar();
$arrayOfFoo = [$f,$b];
test(...$arrayOfFoo);
//will output "foobar"
限制:
这在技术上不是一个解决方案,因为您并没有真正传递一个类型化的数组。相反,您使用数组解包运算符1(函数调用中的“...”)将数组转换为参数列表,每个参数都必须是可变参数声明中提示的类型2(也使用省略号)。
-
函数调用中的“...”是绝对必要的(鉴于上述情况,这并不奇怪)。试图打电话
test($arrayOfFoo)
在上面示例的上下文中会产生类型错误,因为编译器需要 foo 的参数,而不是数组。请参阅下面的解决方案,虽然很老套,但可以直接传入给定类型的数组,同时保留 some 类型提示。
-
可变参数函数可能只有一个可变参数并且它必须是最后一个参数(否则编译器将如何确定可变参数的结束位置和下一个参数的开始位置)意味着您不能按照
function test(Foo ...$foos, Bar ...$bars){
//...
}
或
function test(Foo ...$foos, Bar $bar){
//...
}
仅比仅检查每个元素的替代方案略好:
以下过程 比仅检查每个元素的类型要好,因为 (1) 它保证函数体中使用的参数是正确的类型,而不会使函数与类型检查混淆, (2) 它抛出通常的类型异常。
考虑:
function alt(Array $foos){
return (function(Foo ...$fooParams){
//treat as regular function body
foreach($fooParams as $foo){
$foo->test();
}
})(...$foos);
}
这个想法是定义并返回立即调用的闭包的结果,该闭包会为您处理所有可变参数/解包业务。 (可以进一步扩展该原理,定义一个生成该结构的函数的高阶函数,减少样板文件)。在上面的例子中:
alt($arrayOfFoo) // also outputs "foobar"
这种方法的问题包括:
(1) 特别是对于没有经验的开发者,可能不清楚。
(2) 可能会产生一些性能开销。
(3) 就像在内部检查数组元素一样,将类型检查视为实现细节,因为必须检查函数声明(或享受类型异常)才能意识到只有特定类型的数组才是有效参数。在接口或抽象函数中,无法编码完整的类型提示;唯一能做的就是评论上述类型(或类似的)的实现是预期的。
备注
[1]。简而言之:数组解包呈现等效
example_function($a,$b,$c);
和
example_function(...[$a,$b,$c]);
[2]。简而言之:形式的可变参数函数
function example_function(Foo ...$bar){
//...
}
可以通过以下任何一种方式进行有效调用:
example_function();
example_function(new Foo());
example_function(new Foo(), new Foo());
example_function(new Foo(), new Foo(), new Foo());
//and so on