Web lists-archives.com

Re: [PHP] How do I handle covariant parameters and not fall foul of LSP.




The problem with LSP is that every BaseRepo must be able to be substituted
for any other, but each concrete form only handles its own concrete entity
type. The contract of processEntity(BaseEntity) is "I will process any
concrete BaseEntity subclass", but PersonRepo violates this contract by
declaring that it will only process PersonEntity.

Java uses Generics to solve this, but you'll have to fake it with
instanceof for safety. Note that you're *still* violating LSP here, but you
can't really avoid it given what you want to do.

    class PersonRepo extends BaseRepo
    {
        public function processEntity(BaseEntity $entity)
        {
            parent::processEntity($entity);
            if (!($entity instanceof Person) {
                throw new RepoException('Must be a Person');
            }
            ...
        }
    }

Well, you could invert the responsibility to save LSP by moving the
concrete functionality into the entity, but it will probably be a little
hacky.

    abstract class BaseEntity {
        public abstract function process();
    }

    class PersonRepo extends BaseRepo
    {
        public function processEntity(BaseEntity $entity)
        {
            parent::processEntity($entity);
            $entity->process();
            ...
        }
    }

Cheers!
David