language/oop5/visibility.xml
c1f37a6c270aadbbb3da56a3973ffd62197adf2b
...
...
@@ -3,27 +3,26 @@
3
3
<sect1 xml:id="language.oop5.visibility" xmlns="http://docbook.org/ns/docbook">
4
4
<title>Visibility</title>
5
5
<para>
6
-
The visibility of a property or method can be defined by prefixing
7
-
the declaration with the keywords <emphasis>public</emphasis>,
8
-
<emphasis>protected</emphasis> or
9
-
<emphasis>private</emphasis>. Class members declared public can be
6
+
The visibility of a property, a method or (as of PHP 7.1.0) a constant can be defined by prefixing
7
+
the declaration with the keywords <literal>public</literal>,
8
+
<literal>protected</literal> or
9
+
<literal>private</literal>. Class members declared public can be
10
10
accessed everywhere. Members declared protected can be accessed
11
-
only within the class itself and by inherited classes. Members
12
-
declared as private may only be accessed by the class that defines
13
-
the member.
11
+
only within the class itself and by inheriting and parent
12
+
classes. Members declared as private may only be accessed by the
13
+
class that defines the member.
14
14
</para>
15
15

16
16
<sect2 xml:id="language.oop5.visibility-members">
17
17
<title>Property Visibility</title>
18
18
<para>
19
-
Class properties must be defined as public, private, or
20
-
protected. If declared using <emphasis>var</emphasis>,
21
-
the property will be defined as public.
19
+
Class properties may be defined as public, private, or
20
+
protected. Properties declared without any explicit visibility
21
+
keyword are defined as public.
22
22
</para>
23
-
<para>
24
-
<example>
25
-
<title>Property declaration</title>
26
-
<programlisting role="php">
23
+
<example>
24
+
<title>Property declaration</title>
25
+
<programlisting role="php" annotations="non-interactive">
27
26
<![CDATA[
28
27
<?php
29
28
/**
...
...
@@ -55,7 +54,8 @@ $obj->printHello(); // Shows Public, Protected and Private
55
54
*/
56
55
class MyClass2 extends MyClass
57
56
{
58
-
// We can redeclare the public and protected method, but not private
57
+
// We can redeclare the public and protected properties, but not private
58
+
public $public = 'Public2';
59
59
protected $protected = 'Protected2';
60
60

61
61
function printHello()
...
...
@@ -70,21 +70,139 @@ $obj2 = new MyClass2();
70
70
echo $obj2->public; // Works
71
71
echo $obj2->protected; // Fatal Error
72
72
echo $obj2->private; // Undefined
73
-
$obj2->printHello(); // Shows Public, Protected2, Undefined
73
+
$obj2->printHello(); // Shows Public2, Protected2, Undefined
74
+

75
+
?>
76
+
]]>
77
+
</programlisting>
78
+
</example>
79
+
<sect3 xml:id="language.oop5.visibility-members-aviz">
80
+
<title>Asymmetric Property Visibility</title>
81
+
<simpara>
82
+
As of PHP 8.4, properties may also have their
83
+
visibility set asymmetrically, with a different scope for
84
+
reading (<literal>get</literal>) and writing (<literal>set</literal>).
85
+
Specifically, the <literal>set</literal> visibility may be
86
+
specified separately, provided it is not more permissive than the
87
+
default visibility.
88
+
</simpara>
89
+
<example>
90
+
<title>Asymmetric Property visibility</title>
91
+
<programlisting role="php" annotations="non-interactive">
92
+
<![CDATA[
93
+
<?php
94
+
class Book
95
+
{
96
+
public function __construct(
97
+
public private(set) string $title,
98
+
public protected(set) string $author,
99
+
protected private(set) int $pubYear,
100
+
) {}
101
+
}
102
+

103
+
class SpecialBook extends Book
104
+
{
105
+
public function update(string $author, int $year): void
106
+
{
107
+
$this->author = $author; // OK
108
+
$this->pubYear = $year; // Fatal Error
109
+
}
110
+
}
111
+

112
+
$b = new Book('How to PHP', 'Peter H. Peterson', 2024);
113
+

114
+
echo $b->title; // Works
115
+
echo $b->author; // Works
116
+
echo $b->pubYear; // Fatal Error
74
117

118
+
$b->title = 'How not to PHP'; // Fatal Error
119
+
$b->author = 'Pedro H. Peterson'; // Fatal Error
120
+
$b->pubYear = 2023; // Fatal Error
75
121
?>
76
122
]]>
77
123
</programlisting>
78
124
</example>
79
-
</para>
80
-
<note>
125
+
<para>There are a few caveats regarding asymmetric visibility:</para>
126
+
<itemizedlist>
127
+
<listitem>
128
+
<simpara>
129
+
Only typed properties may have a separate <literal>set</literal> visibility.
130
+
</simpara>
131
+
</listitem>
132
+
<listitem>
133
+
<simpara>
134
+
The <literal>set</literal> visibility must be the same
135
+
as <literal>get</literal> or more restrictive. That is,
136
+
<code>public protected(set)</code> and <code>protected protected(set)</code>
137
+
are allowed, but <code>protected public(set)</code> will cause a syntax error.
138
+
</simpara>
139
+
</listitem>
140
+
<listitem>
141
+
<simpara>
142
+
If a property is <literal>public</literal>, then the main visibility may be
143
+
omitted. That is, <code>public private(set)</code> and <code>private(set)</code>
144
+
will have the same result.
145
+
</simpara>
146
+
</listitem>
147
+
<listitem>
148
+
<simpara>
149
+
A property with <literal>private(set)</literal> visibility
150
+
is automatically <literal>final</literal>, and may not be redeclared in a child class.
151
+
</simpara>
152
+
</listitem>
153
+
<listitem>
154
+
<simpara>
155
+
Obtaining a reference to a property follows <literal>set</literal> visibility, not <literal>get</literal>.
156
+
That is because a reference may be used to modify the property value.
157
+
</simpara>
158
+
</listitem>
159
+
<listitem>
160
+
<simpara>
161
+
Similarly, trying to write to an array property involves both a <literal>get</literal> and
162
+
<literal>set</literal> operation internally, and therefore will follow the <literal>set</literal>
163
+
visibility, as that is always the more restrictive.
164
+
</simpara>
165
+
</listitem>
166
+
</itemizedlist>
167
+
<note>
168
+
<simpara>
169
+
Spaces are not allowed in the set-visibility declaration.
170
+
<literal>private(set)</literal> is correct.
171
+
<literal>private( set )</literal> is not correct and will result in a parse error.
172
+
</simpara>
173
+
</note>
81
174
<simpara>
82
-
The PHP 4 method of declaring a variable with the
83
-
<emphasis>var</emphasis> keyword is still supported for compatibility
84
-
reasons (as a synonym for the public keyword). In PHP 5 before 5.1.3, its
85
-
usage would generate an <constant>E_STRICT</constant> warning.
175
+
When a class extends another, the child class may redefine
176
+
any property that is not <literal>final</literal>. When doing so,
177
+
it may widen either the main visibility or the <literal>set</literal>
178
+
visibility, provided that the new visibility is the same or wider
179
+
than the parent class. However, be aware that if a <literal>private</literal>
180
+
property is overridden, it does not actually change the parent's property
181
+
but creates a new property with a different internal name.
86
182
</simpara>
87
-
</note>
183
+
<example>
184
+
<title>Asymmetric Property inheritance</title>
185
+
<programlisting role="php" annotations="non-interactive">
186
+
<![CDATA[
187
+
<?php
188
+
class Book
189
+
{
190
+
protected string $title;
191
+
public protected(set) string $author;
192
+
protected private(set) int $pubYear;
193
+
}
194
+

195
+
class SpecialBook extends Book
196
+
{
197
+
public protected(set) $title; // OK, as reading is wider and writing the same.
198
+
public string $author; // OK, as reading is the same and writing is wider.
199
+
public protected(set) int $pubYear; // Fatal Error. private(set) properties are final.
200
+
}
201
+
?>
202
+
]]>
203
+
</programlisting>
204
+
</example>
205
+
</sect3>
88
206
</sect2>
89
207

90
208
<sect2 xml:id="language.oop5.visiblity-methods">
...
...
@@ -94,10 +212,9 @@ $obj2->printHello(); // Shows Public, Protected2, Undefined
94
212
protected. Methods declared without any explicit visibility
95
213
keyword are defined as public.
96
214
</para>
97
-
<para>
98
-
<example>
99
-
<title>Method Declaration</title>
100
-
<programlisting role="php">
215
+
<example>
216
+
<title>Method Declaration</title>
217
+
<programlisting role="php" annotations="non-interactive">
101
218
<![CDATA[
102
219
<?php
103
220
/**
...
...
@@ -183,9 +300,72 @@ $myFoo->test(); // Bar::testPrivate
183
300
// Foo::testPublic
184
301
?>
185
302
]]>
186
-
</programlisting>
187
-
</example>
303
+
</programlisting>
304
+
</example>
305
+
</sect2>
306
+

307
+
<sect2 xml:id="language.oop5.visiblity-constants">
308
+
<title>Constant Visibility</title>
309
+
<para>
310
+
As of PHP 7.1.0, class constants may be defined as public, private, or
311
+
protected. Constants declared without any explicit visibility
312
+
keyword are defined as public.
188
313
</para>
314
+
<example>
315
+
<title>Constant Declaration as of PHP 7.1.0</title>
316
+
<programlisting role="php" annotations="non-interactive">
317
+
<![CDATA[
318
+
<?php
319
+
/**
320
+
* Define MyClass
321
+
*/
322
+
class MyClass
323
+
{
324
+
// Declare a public constant
325
+
public const MY_PUBLIC = 'public';
326
+

327
+
// Declare a protected constant
328
+
protected const MY_PROTECTED = 'protected';
329
+

330
+
// Declare a private constant
331
+
private const MY_PRIVATE = 'private';
332
+

333
+
public function foo()
334
+
{
335
+
echo self::MY_PUBLIC;
336
+
echo self::MY_PROTECTED;
337
+
echo self::MY_PRIVATE;
338
+
}
339
+
}
340
+

341
+
$myclass = new MyClass();
342
+
MyClass::MY_PUBLIC; // Works
343
+
MyClass::MY_PROTECTED; // Fatal Error
344
+
MyClass::MY_PRIVATE; // Fatal Error
345
+
$myclass->foo(); // Public, Protected and Private work
346
+

347
+

348
+
/**
349
+
* Define MyClass2
350
+
*/
351
+
class MyClass2 extends MyClass
352
+
{
353
+
// This is public
354
+
function foo2()
355
+
{
356
+
echo self::MY_PUBLIC;
357
+
echo self::MY_PROTECTED;
358
+
echo self::MY_PRIVATE; // Fatal Error
359
+
}
360
+
}
361
+

362
+
$myclass2 = new MyClass2;
363
+
echo MyClass2::MY_PUBLIC; // Works
364
+
$myclass2->foo2(); // Public and Protected work, not Private
365
+
?>
366
+
]]>
367
+
</programlisting>
368
+
</example>
189
369
</sect2>
190
370

191
371
<sect2 xml:id="language.oop5.visibility-other-objects">
...
...
@@ -198,7 +378,7 @@ $myFoo->test(); // Bar::testPrivate
198
378
</para>
199
379
<example>
200
380
<title>Accessing private members of the same object type</title>
201
-
<programlisting role="php">
381
+
<programlisting role="php" annotations="non-interactive">
202
382
<![CDATA[
203
383
<?php
204
384
class Test
...
...
@@ -242,7 +422,6 @@ Accessed the private method.
242
422
</example>
243
423
</sect2>
244
424
</sect1>
245
-
246
425
<!-- Keep this comment at the end of the file
247
426
Local variables:
248
427
mode: sgml
249
428