gpt4 book ai didi

hacklang - 在 Hack 中编写 IoC 容器

转载 作者:行者123 更新时间:2023-12-02 20:06:15 25 4
gpt4 key购买 nike

我正在将 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()Container::getNew() 时,由于返回的是类型 mixed,当我尝试对这些返回的对象执行方法时,它会抛出此错误:

You are trying to access the member x but this is not an object, it is a mixed value

现在我知道这是有道理的,因为混合显然允许非对象,所以我必须确保将此类代码包装在 is_object() 中,但是这样做似乎并不可行抑制类型检查器中的错误。有没有更好的方法来确认某个东西是 Hack 中的对象,并且类型检查器能够理解?

此外,这个 IoC 容器类严重依赖于混合类型,这对我来说有点难看。必须确保其返回值在运行时是对象也是不理想的。我有更好的方法可以做到这一点吗?我确实尝试过将混合更改为接口(interface)(如 IContainable 或其他东西)的想法,并且让我想要存储在容器中的任何类实现此功能,但类型检查器提示 IContainable 接口(interface)不包含该方法我试图调用从容器返回的对象(因此在代码中的同一点出现错误,但原因不同)。也许我用这种方法已经接近成功了?

感谢您的帮助。

最佳答案

Is there a better way to confirm something is an object in Hack, that the type checker will understand?

您可能想通过 instanceof 检查特定实例。例如:(警告,代码直接输入浏览器)

<?hh // strict

class C {
public function f(): void {}
}

function f(): mixed {
return new C();
}

function g(): void {
$c = f();
// $c->f() won't work out here, $c is mixed
if ($c instanceof C) {
$c->f(); // This works now
}
}

另请注意,您不需要 ?mixed,这是多余的 - 只需使用 mixed。 (因为 mixed 可以是任何东西,所以它也可以是 null。当你编写 ?mixed 时生成错误是我在某些时候要做的事情列表中的。:))

Also, this IoC container class relies heavily on the mixed type, which is a bit ugly to me.

你的直觉很好。在 Facebook,我们发现在大多数情况下,我们想要输入混合类型的内容,要么 1) 我们应该编写更具体的类型,要么 2) 代码的结构非常简单很糟糕,我们应该重新考虑如何构建它以更好地打字。

也许您应该使用更具体的类型。正如您所指出的,使用界面会有所帮助。如果事实证明您需要做的大多数事情实际上都是该接口(interface)的一部分,并且您只是偶尔需要做其他事情,那么您可以将其与上述 instanceof 功能结合起来。您可能还想看看using generics ,这可能有意义也可能没有意义,具体取决于您使用 Container 的具体方式。如果 Container 被实例化多次,每次实例化不同的特定子类或接口(interface),那么泛型可能正是您想要的。如果它是单例,那么也许不是。 (此外,虽然您没有在此处显示它,但如果 Container 以任何方式与其保存的类进行交互,您可能需要 constraint on the generic 。)

但我怀疑您遇到这个问题是由于结构性问题。当我遇到这个问题时,我会想到以下一些事情:为什么首先需要围绕实例化类进行这一抽象层——它提供什么功能,以及您能否使该功能同构(即,可打字) )并与异构类实例化问题分开?暂时忽略正式类型(即,如果您是用普通 PHP 编写的),使用 Container 的类如何知道它得到了正确的东西?必须对进出的内容有一定的了解,无论调用代码中的内容是非正式的还是其他方式,否则这首先就行不通!考虑一下这些信息是在哪里以及如何编码的,然后看看是否可以找到一种方法将其明确化。

希望这有帮助!如果我可以澄清任何事情,请在评论中告诉我。当然,请随意继续问这样的问题,许多 FB Hack 工程师以及知识渊博的社区成员都密切关注“hacklang”标签:)(我们真的很高兴人们正在尝试 Hack BTW!希望你是享受它。)

关于hacklang - 在 Hack 中编写 IoC 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23580272/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com