@@ -303,7 +303,157 @@ class Person {
303
303
elements of the array require special care.
304
304
</para >
305
305
</sect2 >
306
+ <sect2 >
307
+ <title >Inheritance</title >
308
+ <sect3 >
309
+ <title >Final hooks</title >
310
+ <para >
311
+ Hooks may also be declared final, in which case they may not be overridden.
312
+ </para >
313
+ <example >
314
+ <title >Final hooks</title >
315
+ <programlisting role =" php" >
316
+ <![CDATA[
317
+ <?php
318
+ class User
319
+ {
320
+ public string $username {
321
+ final set => strtolower($value);
322
+ }
323
+ }
324
+
325
+ class Manager extends User
326
+ {
327
+ public string $username {
328
+ // This is allowed
329
+ get => strtoupper($this->username);
306
330
331
+ // But this is NOT allowed, because set is final in the parent.
332
+ set => strtoupper($value);
333
+ }
334
+ }
335
+ ?>
336
+ ]]>
337
+ </programlisting >
338
+ </example >
339
+ <para >
340
+ A property may also be declared <link linkend =" language.oop5.final" >final</link >.
341
+ A final property may not be redeclared by a child class in any way, which precludes
342
+ altering hooks or widening its access.
343
+ </para >
344
+ <para >
345
+ Declaring hooks final on a property that is declared final is redundant,
346
+ and will be silently ignored. This is the same behavior as final methods.
347
+ </para >
348
+ </sect3 >
349
+ <para >
350
+ A child class may define or redefine individual hooks on a property by redefining the property
351
+ and just the hooks it wishes to override. A child class may also add hooks to a property that had none.
352
+ This is essentially the same as if the hooks were methods.
353
+ </para >
354
+ <example >
355
+ <title >Hook inheritance</title >
356
+ <programlisting role =" php" >
357
+ <![CDATA[
358
+ <?php
359
+ class Point
360
+ {
361
+ public int $x;
362
+ public int $y;
363
+ }
364
+
365
+ class PositivePoint extends Point
366
+ {
367
+ public int $x {
368
+ set {
369
+ if ($value < 0) {
370
+ throw new \InvalidArgumentException('Too small');
371
+ }
372
+ $this->x = $value;
373
+ }
374
+ }
375
+ }
376
+ ?>
377
+ ]]>
378
+ </programlisting >
379
+ </example >
380
+ <para >
381
+ Each hook overrides parent implementations independently of each other.
382
+ If a child class adds hooks, any default value set on the property is removed, and must be redeclared.
383
+ That is the same consistent with how inheritance works on hook-less properties.
384
+ </para >
385
+ <sect3 >
386
+ <title >Accessing parent hooks</title >
387
+ <para >
388
+ A hook in a child class may access the parent class's property using the <code >parent::$prop</code > keyword,
389
+ followed by the desired hook. For example, <code >parent::$propName::get()</code >.
390
+ It may be read as “access the <varname >prop</varname > defined on the parent class,
391
+ and then run its get operation” (or set operation, as appropriate).
392
+ </para >
393
+ <para >
394
+ If not accessed this way, the parent class's hook is ignored. This behavior is consistent with how all methods work.
395
+ This also offers a way to access the parent class's storage, if any.
396
+ If there is no hook on the parent property, its default get/set behavior will be used.
397
+ Hooks may not access any other hook except their own parent on their own property.
398
+ </para >
399
+ <para >
400
+ The example above could be rewritten more efficiently as follows.
401
+ </para >
402
+ <example >
403
+ <title >Parent hook access (set)</title >
404
+ <programlisting role =" php" >
405
+ <![CDATA[
406
+ <?php
407
+ class Point
408
+ {
409
+ public int $x;
410
+ public int $y;
411
+ }
412
+
413
+ class PositivePoint extends Point
414
+ {
415
+ public int $x {
416
+ set {
417
+ if ($value < 0) {
418
+ throw new \InvalidArgumentException('Too small');
419
+ }
420
+ $this->x = $value;
421
+ }
422
+ }
423
+ }
424
+ ?>
425
+ ]]>
426
+ </programlisting >
427
+ </example >
428
+ <para >
429
+ An example of overriding only a get hook could be:
430
+ </para >
431
+ <example >
432
+ <title >Parent hook access (get)</title >
433
+ <programlisting role =" php" >
434
+ <![CDATA[
435
+ <?php
436
+ class Strings
437
+ {
438
+ public string $val;
439
+ }
440
+
441
+ class CaseFoldingStrings extends Strings
442
+ {
443
+ public bool $uppercase = true;
444
+
445
+ public string $val {
446
+ get => $this->uppercase
447
+ ? strtoupper(parent::$val::get())
448
+ : strtolower(parent::$val::get());
449
+ }
450
+ }
451
+ ?>
452
+ ]]>
453
+ </programlisting >
454
+ </example >
455
+ </sect3 >
456
+ </sect2 >
307
457
</sect1 >
308
458
<!-- Keep this comment at the end of the file
309
459
Local variables:
0 commit comments