language/oop5/basic.xml
102a046f5397fc02be82de2d7fca694b2c1ab574
...
...
@@ -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>
...
...
@@ -217,26 +330,27 @@ object(SimpleClass)#1 (1) {
217
330
<programlisting role="php">
218
331
<![CDATA[
219
332
<?php
333
+

220
334
class Test
221
335
{
222
-
static public function getNew()
336
+
public static function getNew()
223
337
{
224
-
return new static;
338
+
return new static();
225
339
}
226
340
}
227
341

228
-
class Child extends Test
229
-
{}
342
+
class Child extends Test {}
230
343

231
-
$obj1 = new Test();
232
-
$obj2 = new $obj1;
344
+
$obj1 = new Test(); // By the class name
345
+
$obj2 = new $obj1(); // Through the variable containing an object
233
346
var_dump($obj1 !== $obj2);
234
347

235
-
$obj3 = Test::getNew();
348
+
$obj3 = Test::getNew(); // By the class method
236
349
var_dump($obj3 instanceof Test);
237
350

238
-
$obj4 = Child::getNew();
351
+
$obj4 = Child::getNew(); // Through a child class method
239
352
var_dump($obj4 instanceof Child);
353
+

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

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