是否可以在文档块中注释通用容器类



假设我有一个类Book,它有一个名为$chapters的属性。在我使用的实现中,这个属性由一个名为Collection的通用帮助类表示,该类又包含一个Chapter类的数组。

示例:


class Book {
/** @var Collection */
public $chapters;
}
class Collection {
private $items;
public function getItems(): array {
return $this->items;
}
}
class Chapter {}

是否可以在Book中注释$chapters属性,以便我的IDE知道它是Collection对象,但对该集合的getItems()方法的调用将返回Chapter实例的数组?

我可以在不创建Collection的子类并对其进行注释的情况下执行此操作吗?

编辑:我觉得我的目标不明确。我想键入一个在Book类之外的类hint,并给出它的$items属性的指导——类似这样的东西(我确信这是无效的(:

class Book {
/**
* @var Collection { 
*   @property Chapter[] $items
* }
*/
public $chapters;
}

对于仍在寻找如何解决这个问题的人来说,以下是基于《诗篇》文章的解决方案"模板化";。

泛型(模板(

如果您在类(甚至函数(中使用变量数据类型,您可以使用所谓的泛型数据类型(在PHP中,这可能被称为模板(。当您需要编写一段代码时,您可以在某些情况下使用通用数据类型,这并不真正关心它使用的类型,但它可能对代码的客户端/用户很重要。换句话说:您希望让代码的用户(Collection(在不直接修改结构的情况下指定结构内部的类型。最好的例子(很方便就是anwswer本身(是集合。

集合实际上并不需要知道它们所持有的数据类型。但对于像您这样的用户来说,这些信息很重要。因此,我们可以Collection中创建通用数据类型,每次有人想使用该类时,他们都可以通过通用类型指定他们希望Collection保持的类型。

/**
* @template T
*/
class Collection
{
/**
* @var T[]
*/
private $items;

/**
* @return T[]
*/
public function getItems(): array
{
return $this->items;
}
}

在这里,我们定义了我们的泛型类型T,它可以由Collection的用户指定,如下所示:

class Book
{
/**
* @var Collection<Chapter>
*/
public $chapters;
}

这样,我们的IDE(或静态分析器(将把Collection内部的通用数据类型识别为Chapter(即T类型变为Book(。

免责声明

尽管这是用PHP编写泛型类型的方法(至少目前是这样(,但根据我的经验,许多IDE都很难解决泛型类型。但幸运的是,像PHPStan这样的分析器知道如何使用泛型。

最新更新