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

简介:

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

2.5 重温未决的类型

在引导范例中,我们看到了当你使用类型检查器的时候,它们能够推断泛型类的类型实参。这里,类型检查器知晓,对于类型形参Tval,Wrapper已经用int类型替代进行实例化了。
$w = new Wrapper(20);
这个推断算法的准确细节已经超出了这里的讨论范围,但是这里仍然有一些需要知晓的结论。
类型检查器应该接受下面的代码吗?

function takes_wrapper_of_int(Wrapper<int> $w): void {
  // ...
}

function main(int $n): void {
  $wrapper = new Wrapper($n);
  takes_wrapper_of_int($wrapper);
}

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

function main(string $str): void {
  $wrapper = new Wrapper($str);
  takes_wrapper_of_int($wrapper);
}

看起来这应该不允许执行,事实也确实如此。
那么,如果我们再换成如下的代码呢?

function main(int $n, string $str): void {
  $w = new Wrapper($n);
  $w->setValue($str);
}

正如我们在第一个例子中看到的一样,类型检查器似乎明白$wrapper在第一行后面是个Wrapper。所以看起来类型检查器应该报告一个错误:在Wrapper上,你不应该对setValue()传递一个字符串作为实参。但是事实上,这段代码是合法的。
这就是类型检查器使用未决的类型的另外一个地方。我们首次接触到它们在1.6.2节,在那里,它们被 “类型检查器用来跟踪一个变量”,这个变量能够在一个程序中的单一点拥有不同的类型,而这决定于达到这个“点”代码的逻辑路径。而对于泛型,类型检查器使用未决的类型来记住那些还没有被明确规定的类型,当类型检查器看到更多的代码后,这里将随时保持对它们进行调整的自由。
在第一行的后面,类型检查器已经非常肯定变量$w是个Wrapper,但是关于它的类型实参是什么,这里还没有明确的指引。它想起以前曾经看到这个对象被当作类型Wrapper进行使用,但是int的类型实参是个未决的类型。于是,它继续向上查看相关调用$w->setValue('a string'),类型检查器查看变量$w的类型,来看这个调用是否合法。当它看到未决的类型实参时,它将把字符串添加到未决的类型中去,而不是抛出一个错误。到此为止,就类型检查器来说,变量$w或者是Wrapper或者是Wrapper。
而对于读者来说,直觉上并不是这样的:很明显在$w内有个字符串。但是类型检查器不知道Wrapper的语义:它并不明白Wrapper只包含单个值。类型检查器所知晓的就是$w好像被当成Wrapper进行使用,还好像是个Wrapper。
当检查到一个未决的类型实参违反某个类型标注的时候,它将变成一个“已决的类型”。这个例子将展示一切相关的内容:

function takes_wrapper_of_int(Wrapper<int> $w): void {
  // ...
}
function main(): void {
  $w = new Wrapper(20);
  takes_wrapper_of_int($w);
  $w->setValue('a string');??// 错误!
}

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

相关文章
|
负载均衡 算法 前端开发
同步和异步
同步和异步
565 0
|
9月前
|
开发工具 git
git的rebase和merge的区别
通过这些内容和示例,您可以深入理解Git的 `rebase`和 `merge`操作及其区别,选择合适的方法进行分支管理,提高版本控制的效率和规范性。希望这些内容对您的学习和工作有所帮助。
1867 5
|
算法 Java 测试技术
letcode的使用方法
letcode的使用方法
453 0
链表的时间复杂度和空间复杂度
链表的时间复杂度和空间复杂度
1330 1
|
机器学习/深度学习 自然语言处理 监控
金融行业的大数据风控模型:构建安全高效的信用评估体系
金融机构借助大数据风控提升信贷效率,通过数据收集、清洗、特征工程、模型构建与评估来识别风险。关键技术涉及机器学习、深度学习、NLP和实时处理。以下是一个Python风控模型构建的简例,展示了从数据预处理到模型训练、评估的过程,并提及实时监控预警的重要性。该文旨在阐述大数据风控的核心要素和关键技术,并提供基础的代码实现概念。【6月更文挑战第23天】
2025 8
|
Java 测试技术
SpringBoot单元测试快速写法问题之区分链路环节是否应该被Mock如何解决
SpringBoot单元测试快速写法问题之区分链路环节是否应该被Mock如何解决
|
开发框架 前端开发 .NET
闲话 .NET(1):.NET Framework
闲话 .NET(1):.NET Framework
|
关系型数据库 MySQL 应用服务中间件
打造专属照片分享平台:快速上手Piwigo网页搭建
打造专属照片分享平台:快速上手Piwigo网页搭建
|
前端开发 API UED
AngularJS的$http服务:深入解析与进行HTTP请求的技术实践
【4月更文挑战第28天】AngularJS的$http服务是核心组件,用于发起HTTP请求与服务器通信。$http服务简化了通信过程,通过深入理解和实践,能构建高效、可靠的前端应用。
|
机器学习/深度学习 人工智能 算法
极智AI | 一文看懂Img2Col卷积加速算法
本教程详细解释了直接卷积计算与Img2Col卷积加速算法的实现原理。
942 0