Can you replace the interface methods with different, but "compatible" signatures?


Consider the following PHP interfaces:

interface Item {
    // some methods here

interface SuperItem extends Item {
    // some extra methods here, not defined in Item

interface Collection {
    public function add(Item $item);
    // more methods here

interface SuperCollection extends Collection {
    public function add(SuperItem $item);
    // more methods here that "override" the Collection methods like "add()" does

I'm using PHPStorm, and when I do this, I get an error in the IDE that basically states the definition for add() in SuperCollection is not compatible with the definition in the interface it extends, Collection.

In one way, I can see this being a problem, as the signature of the method does not match the one it "overrides" exactly. However, I do feel that this would be compatible, as SuperItem extends Item, so I would view add(SuperItem) the same as add(Item).

I'm curious as to if this is supported by PHP (version 5.4 or above), and maybe the IDE has a bug that doesn't properly catch this.

No, I'm pretty sure PHP doesn't support this, in any version, and it would rather defeat the point of an interface.

The point of an interface is that it gives you a fixed contract with other code that references the same interface.

For example, consider a function like this:

function doSomething(Collection $loopMe) { ..... }

This function expects to receive an object that implements the Collection interface.

Within the function, the programmer would be able to write calls to methods that are defined in Collection, knowing that the object would implement those methods.

If you have an overridden interface like this, then you have a problem with this, because a SuperCollection object could be passed into the function. It would work because it also is a Collection object due to the inheritance. But then the code in the function could no longer be sure that it knows what the definition of the add() method is.

An interface is, by definition, a fixed contract. It is immutable.

As an alternative, you could consider using abstract classes instead of interfaces. This would allow you to override in non-Strict mode, although you'll still get errors if you use Strict Mode, for the same reasons.