language/oop5/basic.xml
d0415091861832c03adf6ec8bd3f5322d4be7a45
...
...
@@ -125,6 +125,72 @@ Stack trace:
125
125
</screen>
126
126
</example>
127
127
</warning>
128
+

129
+
<sect3 xml:id="language.oop5.basic.class.readonly">
130
+
<title>Readonly classes</title>
131
+
<para>
132
+
As of PHP 8.2.0, a class can be marked with the
133
+
<modifier>readonly</modifier> modifier.
134
+
Marking a class as <modifier>readonly</modifier> will add the
135
+
<link linkend="language.oop5.properties.readonly-properties"><modifier>readonly</modifier> modifier</link>
136
+
to every declared property, and prevent the creation of
137
+
<link linkend="language.oop5.properties.dynamic-properties">dynamic properties</link>.
138
+
Moreover, it is impossible to add support for them by using the
139
+
<classname>AllowDynamicProperties</classname> attribute. Attempting to do so
140
+
will trigger a compile-time error.
141
+
</para>
142
+
<example>
143
+
<programlisting role="php">
144
+
<![CDATA[
145
+
<?php
146
+
#[\AllowDynamicProperties]
147
+
readonly class Foo {
148
+
}
149
+

150
+
// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
151
+
?>
152
+
]]>
153
+
</programlisting>
154
+
</example>
155
+

156
+
<para>
157
+
As neither untyped nor static properties can be marked with the
158
+
<literal>readonly</literal> modifier, readonly classes cannot declare
159
+
them either:
160
+
</para>
161
+
<example>
162
+
<programlisting role="php">
163
+
<![CDATA[
164
+
<?php
165
+
readonly class Foo
166
+
{
167
+
public $bar;
168
+
}
169
+

170
+
// Fatal error: Readonly property Foo::$bar must have type
171
+
?>
172
+
]]>
173
+
</programlisting>
174
+
<programlisting role="php">
175
+
<![CDATA[
176
+
<?php
177
+
readonly class Foo
178
+
{
179
+
public static int $bar;
180
+
}
181
+

182
+
// Fatal error: Readonly class Foo cannot declare static properties
183
+
?>
184
+
]]>
185
+
</programlisting>
186
+
</example>
187
+
<para>
188
+
A <modifier>readonly</modifier> class can be
189
+
<link linkend="language.oop5.basic.extends">extended</link>
190
+
if, and only if, the child class is also a
191
+
<modifier>readonly</modifier> class.
192
+
</para>
193
+
</sect3>
128
194
</sect2>
129
195

130
196
<sect2 xml:id="language.oop5.basic.new">
...
...
@@ -138,7 +204,7 @@ Stack trace:
138
204
requirement).
139
205
</para>
140
206
<para>
141
-
If a <type>string</type> containing the name of a class is used with
207
+
If a variable containing a <type>string</type> with the name of a class is used with
142
208
<literal>new</literal>, a new instance of that class will be created. If
143
209
the class is in a namespace, its fully qualified name must be used when
144
210
doing this.
...
...
@@ -166,6 +232,53 @@ $instance = new $className(); // new SimpleClass()
166
232
</programlisting>
167
233
</example>
168
234
<para>
235
+
As of PHP 8.0.0, using <literal>new</literal> with arbitrary expressions
236
+
is supported. This allows more complex instantiation if the expression
237
+
produces a <type>string</type>. The expressions must be wrapped in parentheses.
238
+
</para>
239
+
<example>
240
+
<title>Creating an instance using an arbitrary expression</title>
241
+
<para>
242
+
In the given example we show multiple examples of valid arbitrary expressions that produce a class name.
243
+
This shows a call to a function, string concatenation, and the <constant>::class</constant> constant.
244
+
</para>
245
+
<programlisting role="php">
246
+
<![CDATA[
247
+
<?php
248
+

249
+
class ClassA extends \stdClass {}
250
+
class ClassB extends \stdClass {}
251
+
class ClassC extends ClassB {}
252
+
class ClassD extends ClassA {}
253
+

254
+
function getSomeClass(): string
255
+
{
256
+
return 'ClassA';
257
+
}
258
+

259
+
var_dump(new (getSomeClass()));
260
+
var_dump(new ('Class' . 'B'));
261
+
var_dump(new ('Class' . 'C'));
262
+
var_dump(new (ClassD::class));
263
+
?>
264
+
]]>
265
+
</programlisting>
266
+
&example.outputs.8;
267
+
<screen>
268
+
<![CDATA[
269
+
object(ClassA)#1 (0) {
270
+
}
271
+
object(ClassB)#1 (0) {
272
+
}
273
+
object(ClassC)#1 (0) {
274
+
}
275
+
object(ClassD)#1 (0) {
276
+
}
277
+

278
+
]]>
279
+
</screen>
280
+
</example>
281
+
<para>
169
282
In the class context, it is possible to create a new object by
170
283
<literal>new self</literal> and <literal>new parent</literal>.
171
284
</para>
...
...
@@ -364,12 +477,17 @@ echo ($obj->bar)(), PHP_EOL;
364
477
<para>
365
478
The inherited constants, methods, and properties can be overridden by
366
479
redeclaring them with the same name defined in the parent
367
-
class. However, if the parent class has defined a method
368
-
as <link linkend="language.oop5.final">final</link>, that method
369
-
may not be overridden. It is possible to access the overridden
480
+
class. However, if the parent class has defined a method or constant
481
+
as <link linkend="language.oop5.final">final</link>,
482
+
they may not be overridden. It is possible to access the overridden
370
483
methods or static properties by referencing them
371
484
with <link linkend="language.oop5.paamayim-nekudotayim">parent::</link>.
372
485
</para>
486
+
<note>
487
+
<simpara>
488
+
As of PHP 8.1.0, constants may be declared as final.
489
+
</simpara>
490
+
</note>
373
491
<example>
374
492
<title>Simple Class Inheritance</title>
375
493
<programlisting role="php">
...
...
@@ -407,7 +525,8 @@ a default value
407
525
<constant>E_WARNING</constant> level error is generated.
408
526
A signature is compatible if it respects the
409
527
<link linkend="language.oop5.variance">variance</link> rules, makes a
410
-
mandatory parameter optional, and if any new parameters are optional.
528
+
mandatory parameter optional, adds only optional new parameters and
529
+
doesn't restrict but only relaxes the visibility.
411
530
This is known as the Liskov Substitution Principle, or LSP for short.
412
531
The <link linkend="language.oop5.decon.constructor">constructor</link>,
413
532
and <literal>private</literal> methods are exempt from these signature
...
...
@@ -568,9 +687,9 @@ Stack trace:
568
687

569
688
<para>
570
689
The <literal>class</literal> keyword is also used for class
571
-
name resolution. You can get a string containing the fully qualified name
572
-
of the <literal>ClassName</literal> class by using
573
-
<literal>ClassName::class</literal>. This is particularly useful with
690
+
name resolution.
691
+
To obtain the fully qualified name of a class <literal>ClassName</literal>
692
+
use <literal>ClassName::class</literal>. This is particularly useful with
574
693
<link linkend="language.namespaces">namespaced</link> classes.
575
694
</para>
576
695
<para>
...
...
@@ -621,7 +740,7 @@ Does\Not\Exist
621
740
</example>
622
741
</note>
623
742
<para>
624
-
As of PHP 8.0.0, the <literal>::class</literal> constant may also be used on
743
+
As of PHP 8.0.0, <literal>::class</literal> may also be used on
625
744
objects. This resolution happens at runtime, not compile time. Its effect is
626
745
the same as calling <function>get_class</function> on the object.
627
746
</para>
628
747