I want to check if a callable's return type is an instance of another type. For example, let's say I a have:
Pigeon
which extends Animal
.addSupplier()
which takes a callable
argument and expects the return
type to be Animal
.addSupplier()
which passes a closure that returns a Pigeon
.Here is the example in code:
namespace Foo\Bar;
class Animal {
// ...
}
class Pigeon extends Animal {
// ...
}
class Suppliers {
public static function test() {
self::addSupplier(fn() => new Pigeon());
}
public static function addSupplier(callable $callable) {
$reflection = new ReflectionFunction($callable);
$type = $reflection->getReturnType();
if($type->isInstance('\Foo\Bar\Animal')) { // Pseudocode
// It's an animal!
} else
throw new InvalidArgumentException("Callable must return an animal!");
}
}
Is there a way that addSupplier
can check the the return type of the callable parameter to ensure that it will be an instance of Animal
?
As currently written your callable will eventually return a Pigeon
instance, but is not constrainted to do that. If you add a return type hint, your requirement can be implemented. Have a look at this modification:
<?php
namespace Foo\Bar;
class Animal {
// ...
}
class Pigeon extends Animal {
// ...
}
class Suppliers {
public static function test() {
self::addSupplier(fn(): Pigeon => new Pigeon());
}
public static function addSupplier(callable $callable) {
$reflection = new \ReflectionFunction($callable);
$type = $reflection->getReturnType();
if($type && (new \ReflectionClass($type->getName()))->isSubclassOf('\Foo\Bar\Animal')) {
print("It's an animal!");
} else
throw new \InvalidArgumentException("Callable must return an animal!");
}
}
Suppliers::test();
Remove the : Pigeon
hint to see the other case.