PHP类型的返回混合内容



作为一种良好的实践,我已经开始将代码转换为类型化的属性/类型化的函数返回。但我有一个关于混合内容的问题。

我知道返回混合内容通常不是一个好的做法,但我遇到了不可避免的情况。我有一个类,我用它作为数据容器(它有多种功能,但我将跳到基础(:

class Container {
private array $list = [];
public set(string $key, ?? $value): void {
$this->list[$key] = $value;
}
public get(string $key): ?? {
return $this->list[$key];
}
}

我跳过了所有的检查和所有其他功能。关键是list可以容纳任何类型的东西(int、boolean、string、其他类对象…(,那么我应该如何处理呢?

我知道PHP 8将有联合返回类型,所以至少我可以缩小它的范围(int|float|string…(,但由于这是一个很新的类型,我不知道该怎么办。

保持简短。PHP7无法做到这一点。正如您已经说过的,联合类型声明将在PHP8中提供,该声明当天尚未发布。

另一种选择是为您正在处理的每种类型编写集合。您可以使用接口来识别类型。在一个完美的世界里,一切都是一个物体,就像下面的例子一样。

首先是收藏品。

<?php
declare(strict_types=1);
namespace YourAppModel;
use InvalidArgumentException;
use SplObjectStorage;
class TeamCollection extends SplObjectStorage
{
public function attach(object $object, $data = null): void
{
if ($object instanceof Team) {
throw new InvalidArgumentException(sprintf(
'The given object is not a team. %s given.',
get_class($object)
));
}
parent::attach($object, $data);
}
}

这是团队类的集合。它只在将某些东西附加到此集合时接受Team类。否则它将抛出一个异常。由于继承,您不能向Team键入hint对象,因为这会引发另一个错误。SplObjectCollection类将$object参数定义为对象类型。您不能覆盖它。因此,如果给定了Team类,我们可以签入attach方法。

<?php
declare(strict_types=1);
namespace YourAppModel;
use YourAppModelTeamMemberCollection;
use YourAppModelTeamMember;
interface Team
{
public function getName(): ?string;
public function setName(string $name): self;
public function addMember(TeamMember $member): self
public function getMembers(): TeamMemberCollection;
}

接口定义了团队所需的方法。现在我们可以编写团队类了。

<?php
declare(strict_types=1);
namespace YourAppModel;
class SoccerTeam implements Team
{
protected TeamMemberCollection $members;
protected string $name;
public function __construct()
{
$this->members = new TeamMemberCollection();
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function addTeamMember(TeamMember $member): self
{
$this->members->attach($member);
return $this;
}
public function getMembers(): TeamMemberCollection
{
return $this->members;
}
}

这个团队类的例子可以转移到团队成员类。原则上,情况会完全如此。

现在让我们来看看我们的团队收藏以及它是如何工作的。

$teams = new TeamCollection();
$team = (new SoccerTeam())
->setName('Borussia Dortmund');
$teams->attach($team);

这是一个积极的例子。由于SoccerTeam类实现了Team接口,因此它将被团队集合接受。集合本身会检查是否附加了Team实例。任何其他实例都会导致异常。

最新更新