It's not an interface thing. To avoid type checking in the consumers, a method should return one type only. It makes for easier to understand code due to the reduced number of execution pathes through the code.
For instance, this adds unnecessary complexity:
function get_users()
{
// some code returning array when users have been found
// or null when no users have been found
}
$users = get_users();
if (!is_null($users)) {
foreach ($users as $user) {
// do something with $user
}
}
If get_users()
would simply return an empty array when no users have been found, you can simplify the consuming code to just read
foreach (get_users() as $user) {
// do something with $user
}
Also, by virtue of Liskov's Substitution Principle, any classes that are subtypes of a supertype need to be usable interchangeably in a consumer using the supertype. If the consumer expects an integer, you may not return a string since that might break the consumer. The same holds true for classes implementing an interface and consumers of that interface, e.g.
interface Contract
{
/** @return array */
public function fn();
}
Now assume A implements Contract
and returns array, while B implements Contract
and returns array or null. My consumer expecting an array will now break when B returns null:
function fn(Contract $instance)
{
// will break when B returns null
foreach ($instance->fn() as $foo) {
// do something with $foo
}
}
Since PHP cannot currently enforce a return type, it's up to the developer to indicate it in the DocBlock and to make sure the implementing or subtyped classes adhere to that return type.
With that said, if the contract defines multiple possible return types, the consumer has to make sure it can handle them. However, that again means undesirable type checking.