PHP文档-如何指定精确的抽象类型


PHP Doc - How to specify the exact abstract type?

想象下面的抽象接口

interface IDomainRepository {
    /**
     * Finds a Domain Object by the Id
     *
     * @param int $id the id of the object
     *
     * @return IDomainObject the domain object
     */
    public function findById($id);
    //More than that method...
}

现在是一个特定的接口,从IDomainRepository

扩展
interface IUserRepository extends IDomainRepository {
    //More than only extending...
}

如果我调用这样的东西,我希望在这里键入提示而不附加注释(因为我经常使用这个)。

function foo(IUserRepository $repo) {
    $user = $repo->findById(42)
    //Typehint User without @var User $user
}

目前我是这样做的:

/**
 * Interface IUserRepository
 * @method User findById($id)
 */
interface IUserRepository extends  {
}

但是"@method"参数是用于隐藏的魔术方法的。所以这感觉不对。有没有更好的解决方案?

我不应该有一个基本接口,只有一个特定的(这意味着复制&粘贴大约20个方法签名?

由于PHP中没有返回类型提示,但大多数情况下都是关于首选项的,因此根据所使用的IDE,使用@method标记或docblock进行额外的方法声明可能没有区别,因此....

请注意,您不一定要移动方法(并且您很可能不想无论如何,因为它将使IDomainRepository的实现不需要findById()方法),但您可以简单地在必要时在扩展接口中重新声明/覆盖它们,并提供适当的docblock,如@Deele:

所示
interface IUserRepository extends IDomainRepository {
    /**
     * Finds a User by Id
     *
     * @param int $id the id of the object
     *
     * @return IUserRepository the User object
     */
    public function findById($id);
}

我个人认为使用@method更干净的方法,因为它使findById()的具体实现更清楚应该如何行为(通过查看方法声明的代码),并且它预计与基本接口之一不同。

顺便说一下,有一天这也可能"兼容"在PHP RFC中提出的协变返回类型提示:返回类型声明:
// Covariant return-type:
interface Collection {
    function map(callable $fn): Collection;
}
interface Set extends Collection {
    function map(callable $fn): Set;
}

恐怕没有办法做到这一点,因为PHPDoc代码中没有内置这样的深度。

我能想到的唯一节省行数的方法是在您的User类中重复相同的findById()方法,并使其仅调用父方法findById()并添加修改后的@return注释,如

interface IUserRepository extends IDomainRepository {
    /**
     * @see IDomainRepository::findById()
     *
     * @param int $id the id of the object
     *
     * @return IUserRepository the User object
     */
    public function findById($id) {
        return parent::findById($id);
    }
}

PS: findById()按我对OOP逻辑的理解应该是静态函数

我有一个类似的问题,也许static$this作为返回类型可能是你的东西。

背后的思想是指晚期静态绑定

interface IDomainRepository
{
    /**
     * @param int $id the id of the object
     *
     * @return static the domain object
     */
    public function findById($id);
}

interface IUserRepository extends IDomainRepository
{
    /**
     * @param string $name
     *
     * @return static
     */
    public function findUserByName($name);
}

function foo(IUserRepository $repo)
{
    $user = $repo->findById(42);
    $user->find... // suggestions by PHPStorm: findById and findUserByName
}