如何检查Callable返回的ReflectionType是否为指定类型的实例?
如何检查可调用对象的返回类型是否为Animal类(或子类)的实例?
可以实现这个检查,但需要分两种场景处理,取决于传入的可调用对象是否显式声明了返回类型:
1. 可调用对象显式声明返回类型
如果闭包或函数明确标注了返回类型(比如fn(): Animal => new Pigeon()或fn(): Pigeon => new Pigeon()),可以通过反射在不执行可调用对象的前提下完成检查:
namespace Foo\Bar; class Animal { // ... } class Pigeon extends Animal { // ... } class Suppliers { public static function test() { // 两种合法的闭包:声明返回Animal或其子类Pigeon self::addSupplier(fn(): Animal => new Pigeon()); self::addSupplier(fn(): Pigeon => new Pigeon()); } public static function addSupplier(callable $callable) { $reflection = new \ReflectionFunction($callable); $returnType = $reflection->getReturnType(); if ($returnType === null) { throw new \InvalidArgumentException("Callable must declare a return type of Animal or its subclass!"); } $typeName = $returnType->getName(); // 检查类型是否为Animal本身或其子类 if ($typeName === Animal::class || is_subclass_of($typeName, Animal::class)) { // 符合要求,执行后续逻辑 return; } throw new \InvalidArgumentException("Callable must return an Animal instance!"); } }
2. 可调用对象未声明返回类型
如果可调用对象没有标注返回类型,无法通过反射直接获取返回类型信息,只能执行一次可调用对象,然后检查返回值是否为Animal的实例:
public static function addSupplier(callable $callable) { $reflection = new \ReflectionFunction($callable); $returnType = $reflection->getReturnType(); if ($returnType !== null) { $typeName = $returnType->getName(); if ($typeName === Animal::class || is_subclass_of($typeName, Animal::class)) { return; } throw new \InvalidArgumentException("Callable must return an Animal instance!"); } // 无返回类型声明,执行可调用对象检查返回值 // 注意:如果可调用对象需要参数,这里必须传递合法参数,否则会触发错误 $result = $callable(); if ($result instanceof Animal) { return; } throw new \InvalidArgumentException("Callable must return an Animal instance!"); }
注意事项
- 参数问题:如果可调用对象需要接收参数,执行时必须传递符合要求的参数,否则会报错。可以通过
$reflection->getParameters()检查参数是否可选,或者要求调用者必须传递参数。 - 副作用风险:执行可调用对象可能会产生副作用(比如修改数据库、写入文件等),如果不能接受这种副作用,最好强制要求可调用对象必须显式声明返回类型,避免执行操作。
内容的提问来源于stack exchange,提问作者Cardinal System
相关产品推荐
相关产品推荐

