刚刚发现PHP中允许type-hinting,但不能用于整数,字符串,bool或浮点数。
为什么PHP不允许对整数,字符串等类型进行类型提示??
答案 0 :(得分:10)
自PHP 7.0起,支持bool
,int
,float
和string
。 scalar types RFC中添加了支持。有两种模式:弱和严格。我建议阅读RFC以完全理解差异,但基本上类型转换只发生在弱模式下。
鉴于此代码:
function mul2(int $x) {
return $x * 2;
}
mul2("1");
在弱模式下(这是默认模式),这会将"1"
转换为1
。
要启用严格类型,请在文件顶部添加declare(strict_types=1);
。在严格模式下,将发出错误:
致命错误:传递给mul2()的参数1必须是整数类型,给定字符串
答案 1 :(得分:9)
PHP的松散类型,您的“原始”类型会根据它们使用的上下文自动type-juggled。类型提示不会真正改变它,因为字符串可以用作int,反之亦然。类型提示只对数组和对象等复杂类型有帮助,这些类型不能干净地作为整数,字符串或其他基元进行处理。
换句话说,由于PHP没有特定类型的概念,你不能在某处需要 int 因为它不知道 int 到底是什么是。另一方面,对象是某种类型的,因为 MyClass 不能与 MyOtherClass 互换。
仅供参考,以下是尝试在这些类型之间进行转换时所发生的情况(不是详尽的列表):
转换为对象(ref)
“如果将对象转换为对象,则不会对其进行修改。如果将任何其他类型的值转换为对象,则会创建 stdClass 内置类的新实例。 value为NULL,新实例将为空。数组转换为具有按键和相应值命名的属性的对象。对于任何其他值,名为标量的成员变量将包含该值。“
对象为int / float (ref)
未定义的行为
对象布尔(ref)
在PHP5中,始终为TRUE
对象到字符串(ref)
如果适用,将调用对象的__toString()
magic method。
对象到数组(ref)
“如果一个对象被转换为一个数组,结果就是一个数组,其元素是对象的属性。这些键是成员变量名,有一些值得注意的例外:整数属性是不可访问的;私有变量的类名前置于变量名;受保护变量在变量名前加上'*'。这些前置值在任何一方都有空字节。这可能会导致一些意外行为。“
数组到int / float (ref)
未定义的行为
数组到布尔(ref)
如果数组为空(即没有元素),则计算结果为FALSE - 否则为TRUE。
数组到字符串(ref)
字符串“Array”;使用print_r()
或var_dump()
打印数组的内容
阵列到对象(ref)
“数组转换为具有按键和相应值命名的属性的对象。”
答案 2 :(得分:1)
将其称为“类型提示”是不恰当的。 “提示”意味着它是一些可选的输入,仅仅提示而不是要求,但是类型化的函数参数根本不是可选的 - 如果你给它错误的类型,你会得到致命的错误。称之为“类型提示”是一个错误。
现在为什么PHP中的函数参数没有原始类型的原因。 PHP在原始类型之间没有障碍 - 即string,integer,float,bool - 或多或少可以互换,你可以拥有$a = "1";
然后echo $a+3;
并获得4
。所有内部函数也都以这种方式工作 - 如果函数需要一个字符串并且你传递一个整数,它就会被转换为字符串,如果函数需要一个浮点数并得到一个整数,它就会转换成浮点数等。这与对象类型不同 - 例如SimpleXMLElement
和DirectoryIterator
之间没有任何转换 - 两者都没有,它没有任何意义。
因此,如果引入接受整数1
而不是字符串1
的函数,则会在内部函数和用户函数之间创建不兼容性,并为任何假定它们几乎相同的代码创建问题。这将是PHP程序行为方式的一个重大变化,并且需要使用这些函数在所有代码中传播此更改 - 否则您在“严格”和“非严格”代码之间转换时会冒错误。这意味着类型变量,类型属性,类型返回值等的必要性 - 大变化。而且由于PHP不是一种编译语言,因此你不会受到静态类型控制的好处,而且它的缺点是 - 你只会带来不便,但不会增加安全性。这就是PHP中不接受参数输入的原因。
还有另一种选择 - 强制类型,即类似于内部函数的行为 - 在类型之间进行转换。不幸的是,这个不满足严格打字的支持者,因此到目前为止没有找到共识,因此没有一个存在。
另一方面,对象类型从来没有争议 - 显然它们之间没有转换,没有代码假定它们是可互换的,并且检查只能对它们严格,内部和外部函数都是如此。因此,引入严格的对象类型不是问题。