开发者

Why is "traditional" type-hinting not allowed in PHP?

开发者 https://www.devze.com 2023-02-06 02:14 出处:网络
Just discovered that type-hinting is allowed in PHP, but not for ints, strings, bools, or floats. Why does PHP not allow type hinting for types l开发者_运维问答ike integer, strings, ... ?As of PHP 7.

Just discovered that type-hinting is allowed in PHP, but not for ints, strings, bools, or floats.

Why does PHP not allow type hinting for types l开发者_运维问答ike integer, strings, ... ?


As of PHP 7.0 there is support for bool, int, float and string. Support was added in the scalar types RFC. There are two modes: weak and strict. I recommend reading the RFC to fully understand the differences, but essentially type conversions only happen in weak mode.

Given this code:

function mul2(int $x) {
    return $x * 2;
}
mul2("1");

Under weak mode (which is the default mode) this will convert "1" to 1.

To enable strict types add declare(strict_types=1); to the top of the file. Under strict mode an error will be emitted:

Fatal error: Argument 1 passed to mul2() must be of the type integer, string given


PHP's loosely typed, where your "primitive" types are automatically type-juggled based on the context in which they're used. Type-hinting wouldn't really change that, since a string could be used as an int, or vice versa. Type-hinting would only really be helpful for complex types like arrays and objects, which can't be cleanly juggled as ints, strings, or other primitives.

To put it another way, since PHP has no concept of specific types, you couldn't require an int somewhere because it doesn't know what an int really is. On the other hand, an object is of a certain type, since a MyClass is not interchangeable with a MyOtherClass.


Just for reference, here's what happens when you try to convert between such types (not an exhaustive list):

Converting to Object (ref)
"If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty. Arrays convert to an object with properties named by keys, and corresponding values. For any other value, a member variable named scalar will contain the value."

Object to int/float (ref)
undefined behavior

Object to boolean (ref)
in PHP5, always TRUE

Object to string (ref)
The object's __toString() magic method will be called, if applicable.

Object to array (ref)
"If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '*' prepended to the variable name. These prepended values have null bytes on either side. This can result in some unexpected behaviour."

Array to int/float (ref)
undefined behavior

Array to boolean (ref)
If the array is empty (i.e., no elements), it evaluates to FALSE -- otherwise, TRUE.

Array to string (ref)
the string "Array"; use print_r() or var_dump() to print the contents of an array

Array to object (ref)
"Arrays convert to an object with properties named by keys, and corresponding values."


It is not proper to call it "type hinting". "Hinting" implies it's some optional typing, a mere hint rather than requirement, however typed function parameters are not optional at all - if you give it wrong type, you get the fatal error. Calling it "type hinting" was a mistake.

Now to the reasons why there's no primitive typing for function parameters in PHP. PHP does not have a barrier between primitive types - i.e., string, integer, float, bool - are more or less interchangeable, you can have $a = "1"; and then echo $a+3; and get 4. All internal functions also work this way - if the function expects a string and you pass an integer, it's converted to string, if the function expects a float and gets an integer, it is converted to float, etc. This is unlike object types - there's no conversion between, say, SimpleXMLElement and DirectoryIterator - neither there could be, it wouldn't make any sense.

Thus, if you introduce function that accepts integer 1 and not string 1, you create incompatibility between internal functions and user functions and create problems for any code that assumes those are pretty much the same. This would be a big change in how PHP programs behave, and this change will need to be propagated through all the code using such functions - since otherwise you risk errors when transitioning between "strict" and "non-strict" code. This would imply a necessity of types variables, typed properties, typed return values, etc. - big change. And since PHP is not a compiled language, you do not get benefits of static type control with the downsides of it - you only get inconveniences but not the added safety. This is the reason why parameter typing is not accepted in PHP.

There is another option - coercive typing, i.e. behavior analogous to what internal functions do - convert between types. Unfortunately, this one does not satisfy the proponents of strict typing, and thus no consensus is found so far, and thus none is there.

On the other hand, object types were never controversial - it is clear that there's no conversion between them, no code assumes they are interchangeable and checks can only be strict for them, and it is the case with both internal and external functions. Thus, introducing strict object types was not a problem.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号