刚刚发现在PHP中允许使用type-hinting,但不适用于整数、字符串、布尔和浮点数。
为什么PHP不允许对整数、字符串等类型进行类型提示?
刚刚发现在PHP中允许使用type-hinting,但不适用于整数、字符串、布尔和浮点数。
为什么PHP不允许对整数、字符串等类型进行类型提示?
自 PHP 7.0 版本开始,支持 bool
、int
、float
和 string
类型。这项支持是在 标量类型 RFC 中添加的。有两种模式: 弱类型和严格类型。我建议阅读该 RFC 以充分理解它们之间的差异,但基本上只有在弱类型模式下才会发生类型转换。
给定以下代码:
function mul2(int $x) {
return $x * 2;
}
mul2("1");
在弱类型模式下(也是默认模式),这将把"1"
转换为1
。
要启用严格类型,请在文件顶部添加declare(strict_types=1);
。在严格模式下,将发出以下错误:
Fatal error: Argument 1 passed to mul2() must be of the type integer, string given
PHP是一种松散类型的语言,在使用上下文中,您的“基本”类型会自动进行type-juggled。使用类型提示也不会改变这一点,因为字符串可以被用作整数,反之亦然。类型提示只对数组和对象等复杂类型有帮助,因为它们不能像整数、字符串或其他基本类型那样清晰地转换。
换句话说,由于PHP没有特定类型的概念,因此您无法要求在某个地方使用int,因为它不知道int到底是什么。另一方面,一个对象确实是某种类型,因为MyClass不能与MyOtherClass互换。
仅供参考,以下是尝试在这些类型之间进行转换时会发生的情况(不是详尽列表):
转换为对象 (ref)
"如果将一个对象转换为对象,则不会修改它。如果将任何其他类型的值转换为对象,则会创建一个内置类stdClass的新实例。如果该值为NULL,则新实例将为空。数组将转换为具有按键命名的属性和相应值的对象。对于任何其他值,成员变量scalar将包含该值。"
对象转换为int / float (ref)
未定义的行为
对象转换为布尔值 (ref)
在PHP5中始终为TRUE
对象转字符串 (参考)
如果适用,将调用对象的 __toString()
魔术方法。
对象转数组 (参考)
"如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名称,有一些值得注意的例外情况:整数属性无法访问;私有变量在变量名前面加上类名;受保护的变量在变量名前加上 '*'。这些前缀值两侧有空字节。这可能会导致一些意外的行为。"
数组转整数/浮点数 (参考)
未定义的行为
数组转布尔值 (ref)
如果数组为空(即没有元素),则将其评估为FALSE--否则,评估为TRUE。
数组转字符串 (ref)
字符串“Array”;使用print_r()
或var_dump()
打印数组的内容。
数组转对象 (ref)
“数组转换为一个具有由键命名的属性和相应值的对象。”
称之为“类型提示”并不正确。 “提示”意味着它是一种可选的类型,只是一个提示而非要求,但是带有类型的函数参数根本不是可选的 - 如果您输入错误的类型,您会收到致命错误。称之为“类型提示”是一个错误。
现在来看看为什么 PHP 中没有函数参数的原始类型。PHP 没有基本类型之间的障碍 - 即字符串、整数、浮点数、布尔值 - 或多或少可以互换,您可以使用 $a = "1";
然后使用 echo $a+3;
得到 4
。所有内部函数也都是这样工作的 - 如果函数期望一个字符串,而你传递一个整数,它会转换成字符串。如果函数期望一个浮点数,并得到一个整数,它被转换为浮点数等等。这与对象类型不同 - 例如,SimpleXMLElement
和 DirectoryIterator
之间没有转换 - 也不能有,这毫无意义。
1
而不是字符串1
的函数,则会在内部函数和用户函数之间创建不兼容性,并为假定它们几乎相同的任何代码创建问题。这将是PHP程序行为上的重大变化,需要通过使用此类函数的所有代码传播此更改-否则,在“严格”和“非严格”代码之间转换时会出现错误风险。这将意味着需要类型变量、类型属性、类型返回值等-这是一项重大变革。由于PHP不是编译语言,因此您无法获得静态类型控制的好处,但也没有其缺点-您只会遇到不便,而不会增加安全性。这就是为什么PHP不接受参数类型的原因。