《Hack与HHVM权威指南》——第2章 泛型2.1 入门实例

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

第2章

泛型
泛型在Hack的类型系统里面是个非常强大的特性,泛型可以允许你在不知道流程中传入的具体类型的情况下,写出类型安全的代码。一个类或者函数都可以是泛型的,这意味着它可以让调用者来选择传入的参数类型。
泛型结构体最好的例子就是数组和集合类(关于集合类的更多内容请参见第5章)。不具备明确指出数组内容具体类型的能力,它不可能推断出索引自数组的任何值的类型,并且设置数组中的一个值不能被类型检查。这些操作在PHP和Hack中都是非常常见的,并且泛型让类型检查器能够理解并对它们进行核实。
在本章的内容中,我们将对泛型提供的所有特性进行查看和学习。
2.1 入门实例
我们将会从一个非常简单的例子入手学习:一个包含随意值的类。你可能在日常练习中从来没有这么写过这样的代码注1,但是这是一个对泛型进行介绍的最好例子。在本章的学习中,我们讲会使用它作为运行的实例。
为了使一个类“泛型化”,我们可以在类名后面放置一个由尖括号括起来的、逗号分隔的类型形参列表。一个类型形参可以简单理解为:一个用大写T开头的标识符。在泛型类定义内部,可以在变量标准中使用这些类型形参。主要在如下三个常见的位置(属性、方法形参、方法的返回标注类型)。
下面是泛型类的例子:

class Wrapper<Tval> {
  private Tval $value;
  public function __construct(Tval $value) {
    $this->value = $value;
  }
  public function setValue(Tval $value): void {
    $this->value = $value;
  }
  public function getValue(): Tval {
    return $this->value;
  }
}
// There can be multiple type parameters
class DualWrapper<Tone, Ttwo> {
  // ...
}

为了使用这种泛型类,你仅需要像往常一样对它进行实例化,然后使用得到的结果对象即可。

$wrapper = new Wrapper(20);
$x = $wrapper->getValue();

在这个例子中,得益于Wrapper是泛型的,所以类型检查器知道$x是个整数。它能够看到你传递了整数到Wrapper的构造函数中,并且推断出它应该对这个特殊的Wrapper实例的使用进行类型检查,就好像把类定义中所有的Tval用int进行替代一样。
在这种情况下,类型检查过程和你用下面的这个类对Wrapper类进行替代得到的效果一样好。

class WrapperOfInt {
  private int $value;
  public function __construct(int $value) {
    $this->value = $value;
  }
  public function setValue(int $value): void {
    $this->value = $value;
  }
  public function getValue(): int {
    return $this->value;
  }
}

然而,对于泛型版本,你可以对这个类使用任何类型,这具有明显的益处。如果你传递一个字符串类型到Wrapper类的构造函数中,那么这个实例的getValue()方法的返回类型也会是个字符串。你如果你传递一个?float类型的值到Wrapper的构造函数中,那么该实例的getValue()方法的返回类型也将是?float。诸如此类,你可以对能想得到的其他类型进行类似推理判断。
这就是泛型的真实力量:你可以对Wrapper类写一个包含任何类型值的单独实现,但是它仍然是彻底类型安全的。
作为本次说明的最后部分,这里将介绍如何为一个泛型类的实例写一个类型标注。语法是一个类名,随后跟随着被尖括号括起来的、逗号分隔的类型标注列表。在列表中的每个标注都被称作类型实参:

function wrapped_input(): Wrapper<string> {
  $input = readline("Enter text: ");
  return new Wrapper($input);
}

类型形参(type parameter)和类型实参(type argument)的关系就和函数形参(function parameter)和函数实参(function argument)的关系一样。类型实参是泛型类定义中的类型形参在具体使用时的替代品。在本例中,函数返回值是Wrapper类的一个实例,它将告诉类型检查器应该对这个对象的使用进行类型检查,就好像对该类定义中的所有Tval替换为string。
2.2 其他泛型实体
类并不是唯一可以被泛型化的实体。

时间: 2024-11-03 00:34:09

《Hack与HHVM权威指南》——第2章 泛型2.1 入门实例的相关文章

《Hack与HHVM权威指南》——2.6 泛型和亚型

2.6 泛型和亚型 让我们回到关于Wrapper类的引导范例.类型检查器应该接受下面的代码吗? function takes_wrapper_of_num(Wrapper<num> $w): void { // ... } function takes_wrapper_of_int(Wrapper<int> $w): void { takes_wrapper_of_num($w); } 那么问题来了,传递一个整型的wrapper到一个期待值为num的wrapper的话,这个操作是非

《Hack与HHVM权威指南》——第1章 类型检查

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 第1章 类型检查 类型检查器是Hack语言的标志特性,它对Hack程序静态地进行分析(不用运行它们),并且能够检查很多种错误.这就能够在程序开发初期尽量避免bug,并且使程序更容易阅读和理解.为了增强类型检查器的能力,Hack语言允许编程人员显式地在程序体中标注某些变量值的类型,比如函数参数.函数返回值和属性值,类型检

《Hack与HHVM权威指南》——第1章 类型检查1.7 类型提炼

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.7节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.7 类型提炼 假设你有个?string类型的值,而且准备把这个值传递给一个参数类型为string的函数.那么你怎么把一个类型(?string)转化为另外一个类型(string)呢?或者假设你有个object类型的值,它可能实现或没有实现Polarizable接口.同时,如果它实现了这个接口,你还希望调用这个ob

《Hack与HHVM权威指南》——1.7.1 提炼nullable类型到non-nullable类型

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.7.1 提炼nullable类型到non-nullable类型 null检查语句在从空值(nullable)的类型到非空值(non-nullable)类型的转变中经常用到.下面是个通过了类型检查器检查的示例. function takes_string(string $str) { // ... } functio

《Hack与HHVM权威指南》——1.5.1 使用超级全局变量

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.5.1节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.5.1 使用超级全局变量 超级全局变量是在每个代码范围内都存在的全局变量,不需要使用global语句即可使用.这些在运行环境中特殊存在的变量一共有9个,分别是: $GLOBALS $_SERVER $_GET $_POST $_FILES $_COOKIE $_SESSION $_REQUEST $_ENV

《Hack与HHVM权威指南》——1.5.3 属性值初始化

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.5.3节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.5.3 属性值初始化 为了维护类型安全,类型标注过的属性在初始化时,无论是严格模式还是局部模式,类型检查器会强加一些规则.首要目标就是确保属性值在没有初始化为正确类型的值之前,不能被读取. 对于静态的属性值,规则非常简单:任何不可为空的(non-nullable)的静态属性值都必须有一个初始化值.没有显式初

《Hack与HHVM权威指南》——1.4 Hack的类型系统

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.4节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.4 Hack的类型系统 Hack提供了一系列强有力的方法来描述类型,在PHP最基本的布尔型.整型.字符串型.数组等类型系统的基础上,添加了很多新的方式来结合它们,并且使之更富有表现力. 原始类型 这里有和PHP一样的原始类型:bool.int.float.string.array和resource,这些都是合法

《Hack与HHVM权威指南》——1.2.1 自动加载一切

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.2.1节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.2.1 自动加载一切 类型检查器做出的一个关键假设就是,你的项目经过设置后,代码库中的任何类.函数或者常量都能够在你代码库的其他地方使用.不会尝试去分析任何include或者require语句,确保当前文件在使用时已经加载了其他文件.相反,它认为你已经完成了"自动加载"的相关设置.这就简

《Hack与HHVM权威指南》——1.4.1 类型检查器模式

本节书摘来自华章出版社<Hack与HHVM权威指南>一书中的第1章,第1.4.1节,作者 Owen Yamauchi,更多章节内容可以访问"华章计算机"公众号查看. 1.4.1 类型检查器模式 Hack的类型检查器有三种模式:严格(strict).局部(partial)和耦合(decl).这些模式都基于一个个单独的文件,不同模式下的单独文件可以无缝地进行对接.每个文件可以单独声明它的类型检查模式,语法就是在文件的第一行使用一个双斜线的注释.如下面的代码所示:<?hh