dongyi9330 2013-04-17 18:56 采纳率: 100%
浏览 33

如何在接口中使用多态?

I'm attempting to implement something that sort of resemble the the repository pattern. To do this I have a interface that all repos implement and a model base class that all models extend.

I get the following error message from PHP

Fatal error: Declaration of MVCBP\Repositories\UserRepository::add() must be compatible with MVCBP\Core\RepositoryInterface::add(MVCBP\Core\Model $model) in D:\wamp\www\mvc\MVCBP\Repositories\UserRepository.php on line 9

What I want is that my methods in the repository classes should accept an instance of Model as argument according to the Interface. However I want to type hint a specific Model in the implementation. Is this doable in PHP?

RepositoryInterface.php

  <?php
  namespace MVCBP\Core;

  use MVCBP\Core\ModelInterface;

  interface RepositoryInterface
  {
    public function add(ModelInterface $model);
  }

UserRepository.php

<?php
namespace MVCBP\Repositories;

use MVCBP\Core\PDOMySQL;
use MVCBP\Core\RepositoryInterface;
use MVCBP\Models\User;

class UserRepository extends PDOMySQL implements RepositoryInterface
{
    public function add(User $user)
    {
        //Omitted
    }

    //Omitted
}

ModelInterface.php

<?php
namespace MVCBP\Core;

interface ModelInterface {}

User.php

<?php
namespace MVCBP\Models;

use MVCBP\Core\ModelInterface;
use MVCBP\Core\Validate;
use MVCBP\Repositories\UserRepository;

require_once(__DIR__ . '/../lib/password.php');

class User implements ModelInterface
{
    //Omitted
}
  • 写回答

1条回答 默认 最新

  • doubairan4213 2013-04-17 20:32
    关注

    You can do that. You must modify your UserRepository definition. Your add method accept only MVCBP\Core\Model instances.

    UserRepository.php

    <?php
    namespace MVCBP\Repositories;
    
    use MVCBP\Core\PDOMySQL;
    use MVCBP\Core\RepositoryInterface;
    
    //There was another mistake. Your User class is in MVCBP\Models namespace;
    //use MVCBP\Core\Models\User; -> wrong one
    use MVCBP\Models\User; //correct one
    use MVCBP\Core\Model;
    
    class UserRepository extends PDOMySQL implements RepositoryInterface
    {
        public function add(Model $user)
        {
            if (!$user instanceof User)
                throw new \Exception('Exception msg', 101); //example exception
            //Omitted
        }
    
        //Omitted
    }
    

    I prefer to require an interface instance ie.

    public function add(SomeInterface $user)
    {
        if (!$user instanceof User)
           throw new \Exception('Exception msg', 101); //example exception
    }
    
    class User implements SomeInterface {
    //some code
    }
    

    And then ReposituryInterface.php looks like this:

    <?php
    namespace MVCBP\Core;
    
    use MVCBP\Core\Model;
    use MVCBP\Core\SomeInterface;
    
    interface RepositoryInterface
    {
        //We must change method definition so it can take SomeInterface implementation
        public function add(SomeInterface $model);
        public function find($id);
        public function edit(Model $model);
        public function remove($id);
        public function all();
    }
    
    评论

报告相同问题?