language/oop5/inheritance.xml
99744a3bfa1e5c09f75e7ee02a12c92f9e4ef438
...
...
@@ -8,8 +8,9 @@
8
8
many classes and objects relate to one another.
9
9
</para>
10
10
<para>
11
-
For example, when you extend a class, the subclass inherits all of the
12
-
public and protected methods from the parent class. Unless a class overrides
11
+
For example, when extending a class, the subclass inherits all of the
12
+
public and protected methods, properties and constants from the parent class.
13
+
Unless a class overrides
13
14
those methods, they will retain their original functionality.
14
15
</para>
15
16
<para>
...
...
@@ -17,15 +18,54 @@
17
18
implementation of additional functionality in similar objects without the
18
19
need to reimplement all of the shared functionality.
19
20
</para>
21
+
<para>
22
+
Private methods of a parent class are not accessible to a child class. As a result,
23
+
child classes may reimplement a private method themselves without regard for normal
24
+
inheritance rules. Prior to PHP 8.0.0, however, <literal>final</literal> and <literal>static</literal>
25
+
restrictions were applied to private methods. As of PHP 8.0.0, the only private method
26
+
restriction that is enforced is <literal>private final</literal> constructors, as that
27
+
is a common way to "disable" the constructor when using static factory methods instead.
28
+
</para>
29
+
<para>
30
+
The <link linkend="language.oop5.visibility">visibility</link>
31
+
of methods, properties and constants can be relaxed, e.g. a
32
+
<literal>protected</literal> method can be marked as
33
+
<literal>public</literal>, but they cannot be restricted, e.g.
34
+
marking a <literal>public</literal> property as <literal>private</literal>.
35
+
An exception are constructors, whose visibility can be restricted, e.g.
36
+
a <literal>public</literal> constructor can be marked as <literal>private</literal>
37
+
in a child class.
38
+
</para>
20
39

21
40
<note>
22
41
<para>
23
-
Unless autoloading is used, then classes must be defined before they are
42
+
Unless autoloading is used, the classes must be defined before they are
24
43
used. If a class extends another, then the parent class must be declared
25
44
before the child class structure. This rule applies to classes that inherit
26
45
other classes and interfaces.
27
46
</para>
28
47
</note>
48
+
<note>
49
+
<para>
50
+
It is not allowed to override a read-write property with a <link linkend="language.oop5.properties.readonly-properties">readonly property</link> or vice versa.
51
+
<example>
52
+
<programlisting role="php">
53
+
<![CDATA[
54
+
<?php
55
+

56
+
class A {
57
+
public int $prop;
58
+
}
59
+
class B extends A {
60
+
// Illegal: read-write -> readonly
61
+
public readonly int $prop;
62
+
}
63
+
?>
64
+
]]>
65
+
</programlisting>
66
+
</example>
67
+
</para>
68
+
</note>
29
69

30
70
<sect2 xml:id="language.oop5.inheritance.examples">
31
71
<example xml:id="language.oop5.inheritance.examples.ex1">
...
...
@@ -34,7 +74,7 @@
34
74
<![CDATA[
35
75
<?php
36
76

37
-
class foo
77
+
class Foo
38
78
{
39
79
public function printItem($string)
40
80
{
...
...
@@ -47,7 +87,7 @@ class foo
47
87
}
48
88
}
49
89

50
-
class bar extends foo
90
+
class Bar extends Foo
51
91
{
52
92
public function printItem($string)
53
93
{
...
...
@@ -55,8 +95,8 @@ class bar extends foo
55
95
}
56
96
}
57
97

58
-
$foo = new foo();
59
-
$bar = new bar();
98
+
$foo = new Foo();
99
+
$bar = new Bar();
60
100
$foo->printItem('baz'); // Output: 'Foo: baz'
61
101
$foo->printPHP(); // Output: 'PHP is great'
62
102
$bar->printItem('baz'); // Output: 'Bar: baz'
...
...
@@ -68,6 +108,81 @@ $bar->printPHP(); // Output: 'PHP is great'
68
108
</example>
69
109
</sect2>
70
110

111
+
<sect2 xml:id="language.oop5.inheritance.internal-classes">
112
+
<title>Return Type Compatibility with Internal Classes</title>
113
+
114
+
<para>
115
+
Prior to PHP 8.1, most internal classes or methods didn't declare their return types,
116
+
and any return type was allowed when extending them.
117
+
</para>
118
+
119
+
<para>
120
+
As of PHP 8.1.0, most internal methods started to "tentatively" declare their return type,
121
+
in that case the return type of methods should be compatible with the parent being extended;
122
+
otherwise, a deprecation notice is emitted.
123
+
Note that lack of an explicit return declaration is also considered a signature mismatch,
124
+
and thus results in the deprecation notice.
125
+
</para>
126
+
127
+
<para>
128
+
If the return type cannot be declared for an overriding method due to PHP cross-version compatibility concerns,
129
+
a <classname>ReturnTypeWillChange</classname> attribute can be added to silence the deprecation notice.
130
+
</para>
131
+
132
+
<example>
133
+
<title>The overriding method does not declare any return type</title>
134
+
<programlisting role="php">
135
+
<![CDATA[
136
+
<?php
137
+
class MyDateTime extends DateTime
138
+
{
139
+
public function modify(string $modifier) { return false; }
140
+
}
141
+
142
+
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
143
+
?>
144
+
]]>
145
+
</programlisting>
146
+
</example>
147
+
148
+
<example>
149
+
<title>The overriding method declares a wrong return type</title>
150
+
<programlisting role="php">
151
+
<![CDATA[
152
+
<?php
153
+
class MyDateTime extends DateTime
154
+
{
155
+
public function modify(string $modifier): ?DateTime { return null; }
156
+
}
157
+
158
+
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice" as of PHP 8.1.0
159
+
?>
160
+
]]>
161
+
</programlisting>
162
+
</example>
163
+
164
+
<example>
165
+
<title>The overriding method declares a wrong return type without a deprecation notice</title>
166
+
<programlisting role="php">
167
+
<![CDATA[
168
+
<?php
169
+
class MyDateTime extends DateTime
170
+
{
171
+
/**
172
+
* @return DateTime|false
173
+
*/
174
+
#[\ReturnTypeWillChange]
175
+
public function modify(string $modifier) { return false; }
176
+
}
177
+
178
+
// No notice is triggered
179
+
?>
180
+
]]>
181
+
</programlisting>
182
+
</example>
183
+
184
+
</sect2>
185
+

71
186
</sect1>
72
187
73
188
<!-- Keep this comment at the end of the file
74
189