In PHP 7.1.4, using strict typing, I have a simple object oriented setup involving some interfaces, and some classes implementing those interfaces. Below example, as you would expect, works fine.
declare(strict_types=1);
interface Loginable {
public function login();
}
interface Upgradeable {
public function upgrade(): Loginable;
}
class Person implements Upgradeable {
function upgrade(): Loginable {
return new PersonAccount();
}
}
class PersonAccount implements Loginable {
public function login() {
;
}
}
Notice how the upgrade function inside the Upgradable interface requires a Loginable return type, which is another interface. The upgrade method inside the Person class, in this example, specifies a Loginable interface as its return type to match the stipulation of the interface.
However, if I now attempt to specify the return type of the upgrade method of the Person class more accurately, I run into a fatal error.
class Person implements Upgradeable {
function upgrade(): PersonAccount {
return new PersonAccount();
}
}
Please observe that what I am trying to accomplish here is to specify that the upgrade method will return an object that implements the interface that is the required return type according to the interface implemented by the class. This seems very logical and correct to me, however, PHP will say:
Fatal Error: Declaration of Person::upgrade(): PersonAccount must be compatible with Upgradeable::upgrade(): Loginable in [...]
As it has already been pointed out by yivi at https://mcmap.net/q/1317179/-narrowing-down-the-return-type-of-an-implemented-method what I am trying to accomplish is not possible.
I would accept the complaint of PHP if there were extended classes involved, because the extending class could override the original method, and that way there would be no guarantee of the correct return type. However, in the scenario described above, classes are not extended. There are only implementations of interfaces, the whole purpose of which is to explicitly guarantee the correct implementation.
Please shed some light on the reasoning behind the refusal of PHP to accept the above described way of declaring return types!