小白学编程

PHP中declare(strict_types = 1)

2020-06-07  本文已影响0人  正义的程序员

PHP中开启严格模式需要在文件最开始添加declare(strict_types = 1),显示声明,PHP默认是弱类型校验,而且该声明仅对当前文件有效,其他文件includerequire时需要重新在那个文件声明。

看几个例子

两个数相加函数:

function foo (int $a, int $b): int {
    return $a + $b;
}

var_dump(foo(1.0, 2.5));  // 结果是3
var_dump(foo('1', 2));      // 3

在默认若类型下,传过去的float参数被截断成int类型,同样的,字符串在弱模式下也被自动转成了int,再来对比下严格模式:

declare(strict_types=1);

function foo (int $a, int $b): int {
    return $a + $b;
}

var_dump(foo(1.0, 2.5));  // 报错
var_dump(foo('1', 2));  // 报错

// Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be of the type integer, float given, called in /in/JQAi6 on line 10 and defined in /in/JQAi6:6

直接报错了,说foo()只接受int类型,而传过去是float

弱模式下,返回值类型也会被转换:

function foo (): int {
    $r = 1.0;
    return $r;
}

var_dump(foo());  // 1

严格模式下会报错:

declare(strict_types=1);

function foo (): int {
    $r = 1.0;
    return $r;
}

var_dump(foo());  // 报错

// Fatal error: Uncaught TypeError: Return value of foo() must be of the type int, float returned in /in/pRWIl:7

历史

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

先前曾经想添加标量类型声明,例如Scalar Type Hints with Casts RFC,因为各种原因失败了:

这个RFC尝试解决全部问题。

弱类型和强类型

在现代编程语言的实际应用中,有三种主要的方法去检查参数和返回值的类型:

PHP在zend_parse_parameters的标量内部处理机制是采用了弱类型模式。PHP的对象处理机制采用了广泛类型检查方式,并不追求精确匹配和转换。每个方法各有其优缺点

这个提案中,默认采用弱类型校验机制,同时追加一个开关,允许转换为广泛类型校验机制(也就是严格类型校验机制)

为什么两者都支持?

目前为止,大部分的标量类型声明的拥护者都要求同时支持严格类型校验和弱类型校验,并非仅仅支持其中一种。这份RFC,使得弱类型校验为默认行为,同时,添加一个可选的指令来使用严格类型校验(同一个文件中),在这个选择的背后,有很多个原因。

PHP社区很大一部分人看起来很喜欢全静态类型。但是,添加严格类型校验的标量类型声明将会引起一些问题:

这里仍然有相当于一部分人是喜欢弱类型校验的,但是,添加严格类型校验声明和添加弱类型校验声明都会引起一些问题:

第三种方案被提出来了,就是添加区分弱类型和严格类型声明的语法。它也会带来一些问题:

为了解决这三种方案带来的问题,这个RFC提出了第四种方案:每个文件各自定义严格或者弱类型校验。它带来了以下好处:

————
最后,欢迎大家关注我哦。

添加公众号,一起学习,共同进步
上一篇 下一篇

猜你喜欢

热点阅读