Reputation: 3331
I'm trying to specify two interfaces for class A that returns instances of class B, and for class B itself.
I'm declaring return types on the interface.
Say I've got two interfaces.
Some kind of RepositoryInterface, that has a get()
method that returns an object implementing the ElementInterface
<?php
namespace App\Contracts;
interface RepositoryInterface {
public function get( $key ) : ElementInterface;
}
And an element interface:
<?php
namespace App\Contracts;
interface ElementInterface { }
Now, my implementation of the repository declares a return-type that is a specific class MyElement
.
<?php
namespace App\Repositories;
class MyRepository implements RepositoryInterface {
public function get( $key ) : MyElement {
// ...
}
}
Where MyElement
is some class implementing ElementInterface
.
... this results in a fatal error:
Declaration of MyRepository::get( $key ): MyElement must be compatible with RepositoryInterface::get( $key ): ElementInterface
If I would not specify the return types on the interface, this would work perfectly fine. Yet, I want to constrain the type of class returned by any class implementing the RepositoryInterface
.
Upvotes: 2
Views: 583
Reputation: 47319
This is not possible with any version of PHP lower than 7.4.
If your interface contains:
public function get( $key ) : ElementInterface;
Then your class needs to be:
class MyRepository implements RepositoryInterface {
public function get( $key ) : ElementInterface {
returns new MyElement();
// which in turn implements ElementInterface
}
}
The declaration of a class implementing an interface has to match exactly the contract laid out by the interface.
By declaring that it has to return a particular interface instead of an specific implementation, you are giving you leeway on how to implement it (now you could return MyElement
or AnotherElement
as long as both implemented ElementInterface
); but the method declaration has to be the same anyway.
See it working here.
Starting with PHP 7.4, due to be released in November 2019, covariance will be supported for return types. By then, this would work.
Upvotes: 2