Type attributes were added in PHP 7.4 and major improvements were made to PHP's type system. These changes are completely optional and do not break previous versions.
In this article we will take a deeper look at this feature, but first let us summarize the most important points:
● They are available since PHP 7.4
●● They are only available within classes and require access modifiers: public, protected, or private; or var.
● All types are allowed except void and callable
their What actually happens is this:
1 2 3 4 5 6 7 |
|
#Uninitialized
Before looking at the interesting stuff, there is an important aspect of type properties to discuss first.
Despite what you first see, the following code is valid:
1 2 3 4 5 |
|
Even if the value of $bar is not an integer, after making an object Foo, PHP will just throw When an error occurs, $bar is accessed:
1 2 3 |
|
As you can see from the error message, there is a new "variable state": uninitialized.
If $bar has no type, its value will be null. But types can be null, so there's no way to tell if a property of type null was set, or simply forgotten about. That's why "uninitialized" was added.
Four things to remember about uninitialized:
● Uninitialized properties cannot be read, and doing so will result in a fatal error.
● Because uninitialized status is checked when accessing properties, it is possible to create objects with uninitialized properties, even if their type is not nullable.
● You can write to an uninitialized property first and then read it.
● Using unset on a typed property will make it uninitialized, while unsetting an untyped property will make it null.
In particular, note that the following code is valid, in which non-initialized, non-nullable properties are set after constructing the object
1 2 3 4 5 6 |
|
Although the uninitialized, non-nullable property is only checked when reading the property value Initialize state, but do type validation when writing property values. This means you can ensure that any invalid type does not end up as a property value.
#Default Values and Constructors
Let’s take a closer look at how to initialize a typed value. For scalar types, a default value can be provided:
1 2 3 4 5 6 7 8 |
|
Note that you can only use null as the default value if the type is actually empty. This seems obvious, but there is some old behavior with parameter defaults, which allowed the following:
1 2 3 |
|
Fortunately, type attributes do not allow this confusing behavior.
Also note that object or class types cannot have default values. You should use constructors to set their default values.
The obvious place to initialize a typed value is of course the constructor:
1 2 3 4 5 6 7 |
|
But also remember what I mentioned earlier: writing uninitialized properties outside the constructor is valid. As long as nothing is read from the property, the uninitialized check is not performed.
#TYPES OF TYPES
So what exactly can be entered and how? I already mentioned that typed properties are only valid within classes (for now), they need An access modifier or the var keyword precedes them.
For available types, almost all types can be used except void and callable.
Because void means no value, it makes sense that it cannot be used for typed values. callable is slightly different.
It can be seen that "callable" in PHP can be written like this:
But please also remember what I mentioned earlier: writing uninitialized properties outside the constructor is valid. As long as nothing is read from the property, the uninitialized check is not performed.
See, a "callable" in PHP can be written like this:
1 |
|
Suppose you have the following (invalid) code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
In this example, $callable references private Bar::method, but is called in the context of Foo. Due to this issue, it was decided not to add callable support.
This is no big deal, though, because Closure is a valid type and it will remember the $this context in which it was constructed.
By the way, here is the list of all available types:
● bool
● int
● float
● string
● array
● iterable
● object
● ? (nullable)
● self & parent
● Classes & interfaces
# Forced typing and strict typing
PHP is a dynamic language that we love and hate, it will cast types whenever possible. Assuming you pass a string where an integer is expected, PHP will try to automatically convert the string:
1 2 3 |
|
The same principle applies to type attributes.
The code below is valid and converts "1" to 1.
1 2 3 4 5 6 |
|
If you don't like this behavior, you can disable it by declaring strict typing:
1 2 3 4 5 |
|
#Type differences and inheritance
Even PHP 7.4 introduced improved type differences, but type properties remain unchanged.
This means the following is not valid:
1 2 3 4 5 6 7 8 9 10 11 |
|
If the above example doesn't seem important, you should look at the following:
1 2 3 4 5 6 7 8 |
|
Before running the code, PHP will Behind the scenes replaces self with the concrete class it refers to.
这意味着在本例中会抛出相同的错误。处理它的唯一方法,是执行以下操作:
1 2 3 4 5 6 7 8 |
|
说到继承,您可能会发现很难找到任何好的用例来覆盖继承属性的类型。
虽然我同意这种观点,但值得注意的是,可以更改继承属性的类型,但前提是访问修饰符也从private更改为protected或public。
以下代码有效:
1 2 3 4 5 6 7 |
|
但是,不允许将类型从可为空的类型更改为不可为空或反向的类型。
1 2 3 4 5 6 7 8 9 10 11 |
|
翻译:https://stitcher.io/blog/typed-properties-in-php-74
The above is the detailed content of Typed Properties in PHP 7.4. For more information, please follow other related articles on the PHP Chinese website!