PHP7的标量类型声明和强类型校验


声明:本文转载自https://my.oschina.net/fage1151/blog/1540502,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

标量类型声明

PHP从PHP5.0开始已经有对支持class和interface参数类型声明,PHP5.1支持array以及PHP5.4支持callable。这些类型声明让PHP在执行的时候传入正确的参数,让函数签名具有更多的信息。

从PHP7开始,int、float、string和bool会被识别为类型声明,可用于函数返回值类型和参数类型声明

<?php function sum(int $a,int $b):string { 	return $a+$b; } var_dump(sum(1,2)); 

运行以上代码正常 结果为string(1) "3",弱类型校验模式下如果参数不符合声明类型,将会按照php的规则进行转换

PHP7.1添加了可空类型的声明方式并增加了void做为函数返回值类型,强类型检查模式下定义返回类型为 void 的函数不能有返回值,即使返回 null 也不行:

declare(strict_types=1); function returns_one(): void {     return 1; // Fatal error: A void function must not return a value }  function returns_null(): void {     return null; // Fatal error: A void function must not return a value } 

此外 void 也只适用于返回类型,并不能用于参数类型声明,否则会触发错误:

function foobar(void $foo) {  // Fatal error: void cannot be used as a parameter type } 

可空类型声明

可空类型主要用于参数类型声明和函数返回值声明。

主要的两种形式如下:

function answer(): ?int  {     return null; //ok }   function answer(): ?int  {     return 42; // ok }  function say(?string $msg) {     if ($msg) {         echo $msg;     } } 

从例子很容易理解,所指的就是通过 ? 的形式表明函数参数或者返回值的类型要么为指定类型,要么为 null。

此方法也可用于接口函数的定义:

interface Fooable {     function foo(?Fooable $f); } 

但有一个需要注意的地方:如果函数本身定义了参数类型并且没有默认值,即使是可空的,也不能省略,否则会触发错误。如下:

function foo_nullable(?Bar $bar) {}   foo_nullable(new Bar); // 可行 foo_nullable(null); // 可行 foo_nullable(); // 不可行 

但是如果以上函数的参数定义为 ?Bar $bar = null 的形式,则第三种写法也是可行的。因为 = null 实际上相当于 ? 的超集,对于可空类型的参数,可以设定 null 为默认值。

类函数中对于返回类型的声明也不能被子类覆盖,否则会触发错误:

class Foo {     public function bar(): void {     } }   class Foobar extends Foo {     public function bar(): array { // Fatal error: Declaration of Foobar::bar() must be compatible with Foo::bar(): void     } } 

严格校验模式

strict_types/declare()指令

  • 默认情况下,所有的PHP文件都处于弱类型校验模式。新的declare指令,通过指定strict_types的值(1或者0),1表示严格类型校验模式,作用于函数调用和返回语句;0表示弱类型校验模式。

  • declare(strict_types=1)必须是文件的第一个语句。如果这个语句出现在文件的其他地方,将会产生一个编译错误,块模式是被明确禁止的。

  • 类似于encoding指令,但不同于ticks指令,strict_types指令只影响指定使用的文件,不会影响被它包含(通过include等方式)进来的其他文件。该指令在运行时编译,不能修改。它的运作方式,是在opcode中设置一个标志位,让函数调用和返回类型检查符合类型约束。

<?php declare(strict_types=1); function sum(int $a,int $b):string { 	return $a+$b; } var_dump(sum(1,2)); 

以上代码不符合函数的返回值类型声明,将抛出TypeError的错误

<?php declare(strict_types=1); function sum(string $a,string $b):string { 	return $a+$b; } var_dump(sum(1,2)); 

以上代码不符合函数的参数类型声明,也会抛出错误

有一个例外的是,宽泛类型转换是允许int变为float的,也就是说参数如果被声明为float类型,但是它仍然可以接受int参数。

<?php declare(strict_types=1); function sum(int $a,int $b):float { 	return $a+$b; } var_dump(sum(1,2)); 

以上代码运行正常

在这种场景下,我们传递一个int参数给到定义接受float的函数,这个参数将会被转换为float。除此之外的转换,都是不被允许的。

本文发表于2017年09月20日 18:37
(c)注:本文转载自https://my.oschina.net/fage1151/blog/1540502,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 2686 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1