Why is this declaration not compatible?

2019-08-14 16:50发布

问题:

In short I have

abstract class AbstractMapper implements MapperInterface {

    public function fetch(EntityInterface $entity, Array $conditions = array()) {
        . . .
    }

}

interface MapperInterface {

    public function fetch(EntityInterface $entity, Array $conditions = array());

}

abstract class AbstractUserMapper extends AbstractMapper implements UserMapperInterface {

    public function fetch(UserInterface $user, Array $conditions = array()) {

        $conditions = array_merge($conditions, array('type' => $user->getType()));

        return parent::fetch($user, $conditions);
    }

}

interface UserMapperInterface {

    public function fetch(UserInterface $user, Array $conditions = array());

}

This is the error I get:

Fatal error: Declaration of Model\Data\Mappers\AbstractUserMapper::fetch() must be compatible with that of Model\Data\Mappers\Interfaces\MapperInterface::fetch()

If I change the UserInterface to EntityInterface it works but it just seems wrong and also in my AbstractUserMapper::fetch() when I type$user my IDE shows only the methods declared in my EntityInterface and getType() is not in that list.

I know I can still put $user->getType() because I know the object I have implements the UserInterface but it all just seems wrong, even my IDE thinks so or am I missing something here?

Why does this not work? It is messing up my code if I have to put EntityInterface instead of 'UserInterface I think.

回答1:

The problem lies here:

abstract class AbstractUserMapper 
  extends AbstractMapper 
  implements UserMapperInterface 

As the first step, inspect the definition of AbstractMapper:

abstract class AbstractMapper 
  implements MapperInterface

Interface definitions between parent and child classes are transitive, so we can merge the first definition:

abstract class AbstractUserMapper 
  extends AbstractMapper 
  implements UserMapperInterface, MapperInterface

This means that your class needs to implement:

public function fetch(EntityInterface $entity, Array $conditions = array());

public function fetch(UserInterface $user, Array $conditions = array());

And this is not possible, because method overloading doesn't exist in PHP.

Possible solution

Assuming the following interface definitions:

interface EntityInterface {}
interface UserInterface extends EntityInterface {}

I would suggest to drop the implements UserMapperInterface:

abstract class AbstractUserMapper extends AbstractMapper


标签: php oop