《Hack与HHVM权威指南.html.pdf》由会员分享,可在线阅读,更多相关《Hack与HHVM权威指南.html.pdf(103页珍藏版)》请在三一文库上搜索。
1、OReilly Media,Inc.介绍 OReilly Media通过图书、杂志、在线服务、调查研究和会议等方式传播创新知识。自1978年开始,OReilly一直都是前沿发展的见证者和推动者。超级极客们正在开创着未来,而我们关注真正重 要的技术趋势通过放大那些“细微的信号”来刺激社会对新科技的应用。作为技术社区中活跃的参与者,OReilly的发展充满了对创新的倡导、创造和发扬光大。 OReilly为软件开发人员带来革命性的“动物书”;创建第一个商业网站(GNN);组织了影响深远的开放源代码峰会,以至于开源软件运动以此命名;创立了Make杂志,从而成为DIY革命的主要 先锋;公司一如既往地通过
2、多种形式缔结信息与人的纽带。OReilly的会议和峰会集聚了众多超级极客和高瞻远瞩的商业领袖,共同描绘出开创新产业的革命性思想。作为技术人士获取信息的选 择,OReilly现在还将先锋专家的知识传递给普通的计算机用户。无论是通过书籍出版,在线服务或者面授课程,每一项OReilly的产品都反映了公司不可动摇的理念信息是激发创新的力量。 业界评论 “OReilly Radar博客有口皆碑。” Wired “OReilly凭借一系列(真希望当初我也想到了)非凡想法建立了数百万美元的业务。” Business 2.0 “OReilly Conference是聚集关键思想领袖的绝对典范。” CRN “一
3、本OReilly的书就代表一个有用、有前途、需要学习的主题。” Irish Times “Tim是位特立独行的商人,他不光放眼于最长远、最广阔的视野并且切实地按照Yogi Berra的建议去做了:如果你在路上遇到岔路口,走小路(岔路)。回顾过去Tim似乎每一次都选择了小路,而 且有几次都是一闪即逝的机会,尽管大路也不错。” Linux Journal 译者序 2014年3月21日,在PHP业界著名专家“鸟哥”(惠新宸)的新浪微博(Laruence)下面,我第一次看到了Facebook公司的Hack语言及HHVM的相关消息。出于敏锐的职业嗅觉,我注册了相关的cn域 名。在随后的周末,国内第一家H
4、ack语言的中文站(http:/)和第一家HHVM中文站(http:/)正式出炉了。 一个月后在中关村的朔黄大厦,我很幸运地碰到了“鸟哥”,并和他畅谈了理想与人生。在鸟哥的启发下,我不久后就来到了新的工作岗位,开始了新的生活。环境改变了,生活和工作也踏上了新的 征程。 2016年3月21日(很神奇,也是3月21日),机械工业出版社的缪杰编辑找到我,洽谈翻译本书的相关事宜。这正切合我内心深处由来已久的想法,即翻译一本专业的HHVM和Hack编程技术书籍,在中 国范围内,传播最新的Hack语言编程技术知识。我非常强烈地感受到,必须抓住这个机会,完成这本书的翻译。 在2016年4月,我初步尝试翻译了
5、前面的章节。5月到7月上旬,完成了本书大致的翻译。在工作之余以及周末的时间,我都在反复推敲英文原版书中的每个字句,经常熬夜到凌晨两点,这是一段难忘的 经历。翻译同时也是不断学习提高的过程。在完成初稿后,我感觉又重新认识了Hack语言,也重新认识了PHP。 在2016年8月,刘诗灏编辑又给出了很多专业的修改意见。然后,整个译本又经历了几次脱胎换骨的变化,才最终呈现在广大读者的面前。 最后,我要感谢生活给我的磨砺。一份“不服输”的执念引领我在黑暗中不断探索前行。“不经历风雨,哪能见彩虹”,对此我有着更深刻的认识。我还要重点感谢缪杰和刘诗灏编辑。感谢他们在茫 茫人海中发现我,让我能够有机会实现内心最
6、深处的愿望:让Hack语言编程技术在中国范围内得到更好的传播和发展。我还想感谢中国台湾作家张德芬,正是她的身心灵三部曲,伴我走过了那段最黑暗的 时光,让我能够有机会学会接受、放下,学会通过“宇宙的力量”散发“心灵的喜悦”,最后达成“心想事成”。 Hack语言和PHP的伴生与博弈不会停止,Hack语言出身于PHP,而又“高于”PHP的特征,决定了这场争斗会旷日持久。在本书中,你可能会体会到HHVM及Hack语言的使用者对PHP的一些激烈言 辞。同时,如果关注“鸟哥”的新浪微博,你也可以看到他对Hack语言和HHVM的一些反击之词。孰对孰错,见仁见智。 译者简介及联系方式 李苏南(笔名苏南),毕业
7、于华北电力大学。浪迹京城十余载,地处中关村偏北。目前在国内某知名金融投资公司做构架相关的工作。如果您对我感兴趣,欢迎通过国内第一家Hack语言中文网站 (http:/)找到我的联系方式。 由于经验不足等原因,本书的翻译过程不可避免地出现一些纰漏。如果您有疑问,欢迎访问http:/以及http:/,参与我们的在线讨论和互动。同时,本书的相关源 码及勘误表,也可以在上述网站上找到。 在本书出版时,实际的版本内容与书中相比,会不可避免地发生变化。我会在网站上及时地更新和调整。同时,本书中没有提及的“HHVM安装过程”以及“支持Hack语言的编程工具”等内容,也会 在网站中进行补充。 欢迎加入我们的讨
8、论。与大家一起传播Hack语言,让更多的人体会到“更淋漓尽致的编程体验”。 苏南 2016年12月 作者介绍 Owen Yamauchi是一名在Facebook工作的软件工程师,他在HHVM团队工作。在2009年加入Facebook之前,他曾经在VMware和苹果公司实习。Owen在比利时长大,并且在卡耐基梅隆大学获得了计算机 科学学士学位。 封面介绍 本书的封面动物是一只灰色的狐狸(Urocyon cinereoargenteus),它被认为在最原始的犬科动物之间,属于两种唯一存活的灰狐属动物族类之一。另外一种是海峡岛狐(the Channel Island fox)。灰狐是 一种杂食动物,
9、在加拿大南部到南美洲的北部区域都有分布。根据生活区域的不同,它的主要食物也不同,主要有东部棉尾兔(the eastern cottontail)、鼠类、鸟类、啮齿目动物以及野兔。在美国西部的一 些区域,灰狐主要以昆虫和植物为生。所有的灰狐都以水果作为日常饮食。 灰狐以斑白的上半身、黑色尾尖以及强壮的脖子而闻名。公灰狐和母灰狐非常相似,只是母灰狐的个头会稍稍小一些。灰狐包括尾部的长度一般为76到112.5厘米(29.9到44.3英寸),尾部的长度一般 占27.5到44.3厘米(10.8到17.4英寸)的长度。个体重量一般在3.6到7公斤(7.9到15.4磅)。 灰狐非常善于爬树,它们经常和同是犬
10、科动物的亚洲貉(the Asian raccoon dog)分享这种技能。这是它逃避许多食肉动物(家狗或者狼)的策略,来得到树木周围的食物资源。它非常善于使用这种能 力,在逐步的进化中,他可以非常容易地用它锋利的爪子爬上18米高没有枝叶的树干。它通过从一个树枝跳到另外一个树枝,或者缓慢地倒退攀爬下树。灰狐是夜间活动的,它的巢穴一般建于空心树或者 废弃的树桩里面。有的时候,它的巢穴会离地面30英尺高1。 灰狐是一夫一妻制,在北方常在三月上旬进行交配,而在南方一般在二月份。妊娠时间会持续53天,一般产仔数量为1到7只。在三个月大的时候,幼崽开始和父母一起打猎。四个月大的时候,幼崽可 以自己独立觅食
11、。在秋天的时候,年轻的个体将离开它们的家庭组织,到达性成熟。 OReilly的很多封面动物都濒临灭绝,它们对世界非常重要。你可以访问来了解更多你可以做的事情。 封面图片来自Wood的Animate Creation。 1 1英尺=0.3048米 序 2012年,我和Alok Menghrajan开始了一项叫做“strict-mode”的新工作项目。简而言之,项目的目标就是在HHVM的基础之上构建一个静态类型版本的PHP。 从此以后,我着迷于该项目所取得的成功,这个项目后来演变成大家所熟知的Hack语言。这个项目从最开始的类型检查器演变成为一门成熟的编程语言,并且有行业级别的工具做后盾支撑。 回
12、望来路,当第一次向HHVM团队表达我们对项目的想法的时候,我有足够的理由相信他们认为我们疯了。但是最终,我们还是成功地说服了他们,让他们加入了我们的冒险之旅。 在2012年6月底的时候,Facebook网站首次将Hack语言部署应用到产品中。就这样,没有任何管理上的认可,也没有任何形式的过程,Facebook在生产中有了一门新的编程语言。 就在这个时候,我非常期待有人能够及时叫停我们,然而这样的情况却从未发生。 很多工程师跟随着我们的脚步。在我们知道之前,Facebook内部大多数新的代码都使用Hack语言进行编写。于是我们决定把剩余的PHP代码库自动转为Hack语言的代码。我们从动态变量类型
13、的PHP 到静态变量类型的Hack语言,转化了巨大规模(上亿行)的代码。 这个过程是极具挑战性的,挑战主要来自于我们所采用的类型检查器的C/S技术框架,因为PHP开发人员已经习惯于一个快速编辑/刷新的周期,所以我们希望类型检查器有个快速的响应时间。这就是 我们使用Hack语言类型检查服务器的原因:一个背后默默支撑着类型信息的守护进程。当然,最为棘手的问题是如何保持与文件系统相一致的服务器状态。 为了使类型检查服务器更稳定地运行,我们度过了无数个不眠的夜晚。正是如此,也造就了Hack语言如此不平凡的今天。在面临海量代码更新的时候,类型检查器的响应时间几乎是瞬时的(快到可以 自动完成)。 我非常高
14、兴,现在有了这本Hack和HHVM方面的权威指导书。Owen在此做了非常卓越的工作,甚至关于Hack语言的微妙之处,他都做了详细的解释。当然,还有其他一些需要你在Hack/HHVM的 调试及生产过程中知晓的注意事项。 希望你能够享受使用Hack和HHVM的乐趣! Julien Verlaguet,Hack语言之父 前言 在Facebook公司的大部分发展历程中,每隔几个月就会举办“黑客马拉松(hackathons)”活动,活动的目的在于鼓励工程师们碰撞出好的想法,而这些好的想法并不是和他们的日常工作相关的, 他们自由组队,然后在一两天的时间内做出一些非常有意思的事情。 在2007年11月的一次
15、“黑客马拉松”活动上,诞生了一个非常有意思的实验:一个工具能够将PHP程序转化为C+程序,然后还能够用C+编译器进行编译。想法是C+程序将会比PHP原生的程序 运行起来快很多,因为它可以得益于多年以来对C+编译器的大量优化工作。 对于Facebook来说,这种可能性是非常有趣的,因为公司增加了大量新的用户,而支持更多新的用户需要耗费大量的CPU运算周期。所以当你耗尽所有可用的CPU运算周期后,除非你耗费大量财力 购买更多的CPU,用来支持日益增多的用户所带来的CPU运算能力的需求,否则你必须寻找一个方法来降低每个用户的CPU消耗。由于Facebook整个网站的前端都是用PHP语言编写的,所以任
16、何使PHP 代码耗费更少CPU运算周期的新技术都受到欢迎。 在接下来的7年时间里,这个项目的发展远远超出了最开始在“黑客马拉松”中的起点。PHP到C+的转换器称为HPHPc,在2009年的时候它成为支撑Fackbook网页业务唯一的服务器端引擎。在 2010年年初,它以“HipHop for PHP”的名字开源了。然后从2010年起,一个全新的方法用来执行即时编译为机器代码,并没有C+牵扯其中脱胎换骨于HPHPc的代码库,并最终取代它。这 个即时的编辑器称为“HipHop虚拟机”,简称为HHVM,并且在2013年的早期彻底取代了Facebook的网站服务器集群。早期的PHP到C+的转换器消失了
17、,它没有在任何地方进行部署,同时它的代码 都被删除了。 而Hack的起源是完全分开的,其根源在于试图在PHP中使用静态分析以自动探测潜在的安全漏洞的一个项目。很快,事实证明,PHP的本质使得它在非常有用的静态分析方面很难有所进展。于是“严 格模式(strictmode)”的想法就诞生了。对PHP进行修改,增加一些新的特性,比如引用、删除和添加一个补充的复杂类型系统。PHP代码的作者可以自由选择是否使用严格模式,在保持完整的互操作 性同时,获得更加强大的代码检查能力。 Hack的方向从那时开始就作为基于PHP的类型系统掩盖了其本质。它在构建Hack编码的道路上获得了很多有重大影响的新特性,比如异
18、步函数。它添加了很多包括集合在内的新特性,使得类型系统 更加强大。本质上来说,它是一门和PHP不同的新语言,它已经在编程语言方面取得了自己的新位置。 以上就是Hack的发展历程,目前Hack是一门现代化的动态编程语言,它拥有鲁棒的静态类型检查能力,在HHVM上执行。HHVM是一个和PHP无缝兼容且具有互操作性的实时编译运行时引擎。 什么是Hack和HHVM Hack和HHVM是紧密联系在一起的,所以对于这些术语到底指代的是什么会有一些混乱。 Hack是一门编程语言。它基于PHP,继承了PHP中的很多语法,并且完全可以和PHP进行互操作。然而,很可能有人会认为Hack只是在PHP的基础上略加了装
19、饰修改。Hack最核心的特色是鲁棒的静 态类型检查,这已经足够把Hack作为一门编程语言和PHP区分开了。对于现在已经从事已有PHP代码库开发方面工作的开发者来说,这是非常有益的。在这种情形下,将会给这些开发者很多的启迪,当 然,对于新项目的底层开发也是一个非常不错的选择。 除了静态类型检查外,Hack还拥有PHP没有的很多项新特性,本书将对这些新特性进行阐述:异步函数、XHP等。出于解决一些粗糙边界问题的目的,Hack也故意缺失了对一些PHP特性的支持。 HHVM是一个执行引擎,它同时支持PHP和Hack。它让两种语言可以互操作:PHP书写的代码能够调用Hack代码,反之亦然。当执行PHP的
20、时候,它的目标在于对PHP.net提供的PHP标准解释器进 行替换。本书中有些章节的内容是关于HHVM的:如何配置并部署它,如何使用它调试和配置代码。 最后,我们要介绍的就是从HHVM中分离出来的Hack类型检查器:这是一个能够分析Hack代码(而不是PHP代码)然后报告类型错误的程序。在它能够接受的代码方面,类型检查器目前要比HHVM 严格一些。当然,在未来的发行版本中,HHVM应该比类型检查器更加严格。目前,除了你在命令行里面启动它的命令“hh_client”外,类型检查器还没有个定型的名字,我更倾向于叫它“Hack类型检 查器”(Hack typechecker)或者就叫做“类型检查器”
21、(typechecker)。 到目前为止,HHVM是运行Hack的唯一执行引擎,这也是有时它们会混为一谈的原因。 本书读者对象 本书适合那些已经对编程有一定基础的读者。这里并没有花费时间解释很多编程语言里面常见的概念。例如控制流、数据类型、函数、面向对象编程等。 Hack派生于PHP,本书不会特别解释PHP中常见的语法,除非Hack里面相关的语法知识点与之不同。所以有PHP的知识基础将会非常有用。如果你从来没有使用过PHP,但是有其他编程语言的相关 经验,那么你仍然能够读懂本书里面的大部分代码。语法知识点都是非常易于理解的。 如果你拥有PHP相关经验,但是从未工作在一个复杂、高负载的PHP网站
22、环境中,你也不必担心这里有什么你看不懂的。无论你的代码是简单独立运行的小脚本,还是数以百万行级别像Facebook一样 的大型Web应用,Hack对于任何规模的代码库都大有裨益。 这里有一些材料假设你对传统的Web应用已经熟悉,例如关系数据库查询、使用memcached(见第6章)和生成HTML(见第7章)。如果它们和你不相关,那么你可以跳过这些章节。但是事实上, 对这些章节的理解并不需要什么特别的知识,哪怕是小的基础网站应用的开发经验。 我希望本书并不仅仅用来解释事物具体是什么的,而且希望介绍它是怎样的运作原理。程序语言设计是一个很困难的问题。它本质上是一门对上百个可能的方案统一进行权衡的艺
23、术,同时它还受向后 兼容的相关内容的制约,Hack也不例外。所以如果你对“一门程序语言如何通过一系列不同寻常的限制来成就未来”这个案例学习感兴趣,那么本书将会提供你所需要的内容。 哲学理念 在Hack和HHVM设计的背后存在着一些理念。这些理念可以帮助你理解事物的运转方式。 程序类型 这里有个单独的观察程序用于指引HHVM优化和执行代码的方式,还指引Hack验证它的方式。它就是隐藏在大多数动态语言程序背后的一个静态类型的程序。 看一下如下代码,这段代码在PHP和Hack下都可以正常运行: for ($i = 0; $i 在Hack语言中是不生效的,所以不能在Hack语言中使用PHP“模板化语言
24、(templating-language)”的语法了。 文件的扩展名无关紧要,按照约定命名为.hh文件或者.php文件都是可以的。 一旦类型检查服务端被启动,如果在你的项目中没有Hack文件(也就是说,你的所有代码都包裹在 $nums): (int, float) $max = -INF; $max_index = -1; foreach ($nums as $index = $num) if ($num $max) $max = $num; $max_index = $index; return tuple($max_index, $max); 元组类型的表现更像一个受限版的数组类型,你不能
25、修改元组类型的key集合,也就是说,你不能添加或者移除对象。你能够修改一个元组中的值,但是你不能修改它们的类型。你能够通过数组编号的 语法读出元组内的值,但是更通常的做法是通过列表分配把元组类型解包,而不是读取某个单独的元素。 从底层上讲,元组类型确实就是数组,如果你把一个元组类型传递给函数is_array(),这个函数将会返回true。 混合型(mixed) mixed意味着包含null在内的Hack编程语言里面所允许的任何值。 void void只在函数返回类型中有效,它意味着这个函数什么也没有返回。(在PHP中,如果一个函数什么也不返回的话,那么事实上返回了一个null的值。但是在Hac
26、k中,函数返回值返回viod的话会引发 一个错误。) void包含在mixed类型中,也就是说,如果一个函数的返回类型是mixed,那么它什么也不返回是合法的。 this this只在方法返回类型中有效,对于一个空函数来说,this并不是一个有效的返回类型。这表明这个方法返回了一个类的对象,该对象的类与这个方法调用时所在对象的类相同。 这种类型标注的目的就是允许在有子类的类上进行链式方法调用,链式方法调用是个非常有用的技巧,它们看起来是这样的: $random = $rng-setSeed(1234)-generate(); 为了实现写链式调用,题目中的类必须从那些没有逻辑返回值的方法返回$t
27、his,就像这样: class RNG private int $seed = 0; public function setSeed(int $seed): RNG $this-seed = $seed; return $this; / http:/ 在这个例子中,如果类RNG没有子类,你可以使用RNG作为setSeed()方法的返回类型标注,这不会有任何问题,但是当RNG有子类的时候,就会出问题了。 在接下来的例子中,类型检查器将会报告一个错误。因为方法setSeed()的返回类型是RNG,它认为调用$rng-setSeed(1234)将会返回一个RNG类型,并且在RNG对象上调用 gene
28、rateSpecial()方法是非法的,因为这个方法仅仅定义在子类中。更多$rng变量特别指明的类型(类型检查器知道这个类型是SpecialRNG)已经丢失了。 class SpecialRNG extends RNG public function generateSpecial(): int / http:/ function main(): void $rng = new SpecialRNG(); $special = $rng-setSeed(1234)-generateSpecial(); 返回类型标注this巧妙地解决了这个问题: class RNG private int $s
29、eed = 0; public function setSeed(int $seed): this $this-seed = $seed; return $this; / http:/ 现在,当类型检查器计算$rng-setSeed(1234)调用的返回类型的时候,this变量标注将告诉它保持箭头左边表达式的类型,这就是说,关于generateSpecial()的链式调用将是合法的。 静态方法也能够使用返回类型this,在这种情况下,它表明它们返回了一个对象,这个对象的类就是这个方法所在的类,就是说,从函数get_called_class()返回的类的名字。满足this类型标注的办 法就是返回
30、new static(): class ParentClass / 这里需要告之类型检查器 new static()是合法的 final protected function _construct() public static function newInstance(): this return new static(); class ChildClass extends ParentClass function main(): void ParentClass:newInstance(); /返回一个ParentClass的实例 ChildClass:newInstance(); / 返
31、回一个ChildClass 的实例 类型别名 在3.2节中将详细阐述,类型别名是对已经存在的类型重新命名的好办法,你可以使用新名字作为类型标注。 Shape Shape类型是个非常特别的类型别名,将在3.3节中详细描述,并且它们的名字也能够作为类型标注使用。 Nullable类型 除void和mixed之外的所有类型都能够通过问号前缀符号标注为可为空的。对于?int的类型标注来说,它能够是整型也可以是null类型。mixed类型不能够标注为nullable的原因就是它已经包含了null 类型。 Callable类型 虽然PHP允许callable作为一个参数的类型提示,但是Hack并不允许。相
32、反,Hack提供了更为强大的语法,允许你明确指出不仅仅一个值是可调用的,还包括它作为参数值时是什么类型的,以及它返 回的是什么类型。 这个类型的语法是一个关键词function,后面是括号括住的参数类型列表,再后面是冒号和返回类型,上述这些再包在一个括号内。这有些像给函数做变量标注的语法;从根本上来说,这就是一个没 有函数名和参数名的函数签名。在下面的例子中,$callback就是这样一个函数,它的参数是一个整型和一个字符串类型,返回字符串类型: function do_some_work(array $items, (function(int, string): string) $callb
33、ack): array foreach ($items as $index = $value) $string_result = $callback($index, $value); / http:/ 满足callable类型标注的callable值有四种情况:闭包、函数、实例方法和静态方法。让我们通过下面的例子加深一下理解: 下面是一个简单的闭包的例子: function do_some_work(function(int): void) $callback): void / http:/ function main(): void do_some_work(function (int $x
34、): void /* http:/ */ ); 如果要使用一个已经命名的函数作为callable的值,你需要通过一个特别的函数fun()来传递函数名,例如: function do_some_work(function(int): void) $callback): void / http:/ function f(int $x): void / http:/ function main(): void do_some_work(fun(f); fun()函数的参数必须是一个单引号的字符串字面量,类型检查器会自动查找函数名,并且检测它的参数类型和返回类型,然后把fun()当成它返回了一个正确类
35、型的callable的值。 当使用实例方法作为callable的值时,你必须通过特殊的函数inst_meth()来传递对象及方法名,这点和fun()函数很像,类型检查器将会查找对应名称的方法,并且将inst_meth()当成它返回了正 确类型的callable值一样。再次说明一下,方法名必须是单引号的字符串字面量: function do_some_work(function(int): void) $callback): void / http:/ class C public function do_work(int $x): void / http:/ function main():
36、void $c = new C(); do_some_work(inst_meth($c, do_work); 使用静态方法也非常相似:把类名和方法名通过函数class_meth()传递即可。方法名必须是个单引号的字符串字面量。类名可以是个单引号的字符串字面量,或者是Hack中特有的:class构造附加 在一个非单引号的类名后面。 function do_some_work(function(int): void): $callback): void / http:/ class C public static function prognosticate(int $x): void / ht
37、tp:/ function main(): void do_some_work(class_meth(C:class, prognosticate); /等价于: do_some_work(class_meth(C, prognosticate); 在运行环境中,ClassName:class是和ClassName等价的。 这里还有另外一种办法来创建一个调用实例方法的callable值,这就是meth_call()函数。它将通过调用你传递给它的一个实例对象上的方法,来创建一个可调用的值。这里有个局限性,就是,这个 方法必须没有任何参数,这个局限性在未来的版本中将被解除。 class C fun
38、ction speak(): void echo “hi!“; function main(): void $caller = meth_caller(C:class, speak); $obj = new C(); $caller($obj); /等价于调用$obj-speak(); 与能够打包一个特定对象和调用它的方法的函数inst_meth()相比,meth_caller()函数与array_map()和array_filter()这样的工具函数一起使用特别有用。例如: class User public function getName(): string / http:/ funct
39、ion all_names(array $users): string $names = array_map($users, meth_caller(User:class, getName); return implode(, , $names); 当然,有一种值在PHP中是可调用的,但是在Hack的类型检查器中却不能识别:拥有一个_invoke()方法的对象。这个问题未来将会被改进。 泛型 也被称作参数化类型,泛型允许一段代码在同一方式下使用多种不同的类型,并且保证仍然可验证为类型安全的。最简单的例子是取代简单指定一个值是一个数组,你可以通过泛型指定一个字符串组 成的数组,或者由一个Pers
40、on类的对象组成的数组等。 泛型是非常强大的工具,这里仅做简单了解,我们将在第2章做全面的阐述。 对于本章而言,已经足够了解泛型数组的语法了。它通常由关键词array开头,然后紧随着的是一个或者两个由尖括号包住的类型名称。如果在尖括号内只有一个值,那么这个类型就是数组中value的 类型,并且数据的key被认为是int类型。如果尖括号内有两个类型,那么第一个就是key的类型,第二个就是value的类型。举例说明如下:array意味着整型数组的key映射到布尔型的值,而 array意味着字符串类型的key映射到整型。尖括号里面的类型被称为类型实参。 需要重点说明的是,一个值如果在PHP中不能被创
41、建,那么在Hack中你也不能创建这个值。PHP和Hack的基础元素都是一致的,Hack的类型系统仅仅为更有意思的组合和可能值的子集提供了新的表 述方式。 更具体地说,请思考下面的代码: function main(): void f(10, 10); function f(mixed $m, int $i): void / http:/ 在函数f()的函数体内,我们说$m是一个mixed类型的变量,而$i是一个int类型的变量,虽然它们实际上存储的是同样的东西。 或者想想下面的代码: function main(): void $callable = function(string $s):
42、?int /* http:/ */ ; 虽然我们说变量$callable是(function(string):?int)类型,但是在此情况下,它和其他闭包一样,仍然是个对象。它并不是一个仅在Hack中存在的神奇函数指针,或者其他类似的概念。 一般来说,如果我们表述某个变量是某个类型的话,这个表述是类型检查器知晓的,但并不是运行环境所知晓的。 1.4.1 类型检查器模式 Hack的类型检查器有三种模式:严格(strict)、局部(partial)和耦合(decl)。这些模式都基于一个个单独的文件,不同模式下的单独文件可以无缝地进行对接。每个文件可以单独声明它的类型检 查模式,语法就是在文件的第一
43、行使用一个双斜线的注释。如下面的代码所示: go(); 而改为这样做: go(); main(); 更好的做法是把main函数的定义放到一个严格模式的文件中。 引用是允许的,但是类型检查器本质上假装引用的相关代码不存在,并不会试图去规范它们的行为。在本例中,代码的最后一行后面类型检查器仍然会认为$a是个整型,尽管事实上它是一个字符串 类型。 $a = 10; $b = $b = not an int; 简单来说,可以在局部模式下使用引用,但是这破坏了类型安全,所以你应该尽量避免使用它们。 甚至对于一个从头开始建立的新Hack项目来说,这里仍然有局部模式的文件需求。在任何的脚本或者Web应用中,总是需要有一定数量的顶层代码的存在,它们将作为入口点代码存在。所以你将至少 需要一个局部模式的Hack文件。你需要使用局部模式来获得超级全局变量,比如$_GET、$_POST和$argv,我们将在1.5.1节对此展开更详细的阐述。 耦合模式:unknown_method(); / 没有错误 $c-known_method(12); / 错误 : int类型并不兼容 string类型 $c-unknown_property-func(); / 没有错
链接地址:https://www.31doc.com/p-5519048.html