我正在将 PHP 项目转换为 Hack,但遇到了一些障碍。我正在尝试做的是将 IoC 容器从 PHP 重写为 Hack,我在让所有内容都通过 Hack 类型检查器工具时遇到了一些麻烦。
所以基本上我拥有的是一个容器,它可以让你将字符串注册到闭包映射。这个想法是闭包包含实例化一个类的逻辑。容器还存储它创建的实例,还允许您强制创建新实例。这是我的容器代码:
<?hh // strict
class Container {
private Map<string, mixed> $instances = Map {};
private Map<string, (function (Container): mixed)> $registered = Map {};
public function register(string $alias, (function (Container): mixed) $closure): void
{
$this->registered[$alias] = $closure;
}
public function get(string $alias): ?mixed
{
if (!$this->registered->contains($alias)) {
return null;
}
$instance = $this->instances->get($alias);
if ($instance !== null) {
return $instance;
}
$closure = $this->registered->get($alias);
if ($closure !== null) {
$this->instances->set($alias, $closure($this));
}
return $this->instances->get($alias);
}
public function getNew(string $alias): ?mixed
{
if (!$this->registered->contains($alias)) {
return null;
}
$closure = $this->registered->get($alias);
return ($closure !== null) ? $closure($this) : null;
}
}
这个类本身似乎通过了类型检查器,但是当使用Container::get()
or时Container::getNew()
,由于返回是 type mixed
,当我尝试对这些返回的对象执行方法时,它会抛出此错误:
您正在尝试访问成员 x 但这不是一个对象,它是一个混合值
现在我知道这是有道理的,因为混合显然允许非对象,所以我必须确保将此类代码包装在 a 中is_object()
,但是这样做似乎并不能抑制类型检查器中的错误。有没有更好的方法来确认某个东西是 Hack 中的一个对象,类型检查器会理解?
另外,这个 IoC 容器类严重依赖于混合类型,这对我来说有点难看。在运行时必须确保它的返回是对象也不理想。有没有更好的方法可以做到这一点?我确实尝试过将混合更改为接口(如 IContainable 或其他东西)的想法,并让我想存储在容器中的任何类实现这一点,但随后类型检查器抱怨 IContainable 接口不包含该方法我试图调用从容器返回的对象(因此代码中的同一点出现错误,但原因不同)。也许我用这种方法接近成功了?
谢谢你的帮助。