天天看点

《Hack与HHVM权威指南》——2.5 重温未决的类型

本节书摘来自华章出版社《hack与hhvm权威指南》一书中的第2章,第2.5节,作者 owen yamauchi,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

在引导范例中,我们看到了当你使用类型检查器的时候,它们能够推断泛型类的类型实参。这里,类型检查器知晓,对于类型形参tval,wrapper已经用int类型替代进行实例化了。

<code>$w = new wrapper(20);</code>

这个推断算法的准确细节已经超出了这里的讨论范围,但是这里仍然有一些需要知晓的结论。

类型检查器应该接受下面的代码吗?

直觉上来说,它应该是被接受的,事实也是这样。类型检查器知道在main()函数的最后一行,变量$wrapper是一个整型的wrapper,所以允许这个调用。

那么,换成下面的代码呢?

看起来这应该不允许执行,事实也确实如此。

那么,如果我们再换成如下的代码呢?

正如我们在第一个例子中看到的一样,类型检查器似乎明白$wrapper在第一行后面是个wrapper。所以看起来类型检查器应该报告一个错误:在wrapper上,你不应该对setvalue()传递一个字符串作为实参。但是事实上,这段代码是合法的。

这就是类型检查器使用未决的类型的另外一个地方。我们首次接触到它们在1.6.2节,在那里,它们被 “类型检查器用来跟踪一个变量”,这个变量能够在一个程序中的单一点拥有不同的类型,而这决定于达到这个“点”代码的逻辑路径。而对于泛型,类型检查器使用未决的类型来记住那些还没有被明确规定的类型,当类型检查器看到更多的代码后,这里将随时保持对它们进行调整的自由。

在第一行的后面,类型检查器已经非常肯定变量$w是个wrapper,但是关于它的类型实参是什么,这里还没有明确的指引。它想起以前曾经看到这个对象被当作类型wrapper进行使用,但是int的类型实参是个未决的类型。于是,它继续向上查看相关调用$w-&gt;setvalue('a string'),类型检查器查看变量$w的类型,来看这个调用是否合法。当它看到未决的类型实参时,它将把字符串添加到未决的类型中去,而不是抛出一个错误。到此为止,就类型检查器来说,变量$w或者是wrapper或者是wrapper。

而对于读者来说,直觉上并不是这样的:很明显在$w内有个字符串。但是类型检查器不知道wrapper的语义:它并不明白wrapper只包含单个值。类型检查器所知晓的就是$w好像被当成wrapper进行使用,还好像是个wrapper。

当检查到一个未决的类型实参违反某个类型标注的时候,它将变成一个“已决的类型”。这个例子将展示一切相关的内容:

这次,类型检查器将在最后一行报告一个错误。当变量$w被传递给函数takes_wrapper_of_int()时,检查到它违反了函数的形参类型标注。在这点上,变量$w的类型是“已决的”。类型检查器已经看到变量$w应该是一个wrapper类型的确凿证据。既然这个类型是“已决的”了,类型检查器在对setvalue()方法的调用检查上也就不会宽大处理了。在一个已决的类型wrapper的wrapper实例上调用“setvalue('a string')”是非法的,所以类型检查器报告了一个错误。