-
Notifications
You must be signed in to change notification settings - Fork 103
/
inheritance.xml
186 lines (165 loc) · 5.76 KB
/
inheritance.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: f94d903985119d3ac00f4528551df947f57b667f Maintainer: Haohappy Status: ready -->
<!-- CREDITS: Luffy, mowangjuanzi -->
<sect1 xml:id="language.oop5.inheritance" xmlns="http://docbook.org/ns/docbook">
<title>对象继承</title>
<para>
继承已为大家所熟知的一个程序设计特性,PHP 的对象模型也使用了继承。继承将会影响到类与类,对象与对象之间的关系。
</para>
<para>
比如,当扩展一个类,子类就会继承父类所有 public 和 protected 的方法,属性和常量。除非子类覆盖了父类的方法,被继承的方法都会保留其原有功能。
</para>
<para>
继承有助于功能的设计和抽象,在实现类似的对象、增加新功能时,无须重复编写这些公用的功能。
</para>
<para>
子类无法访问父类的私有方法。因此,子类无需考虑正常的继承规则而重新实现私有方法。
然而,在 PHP 8.0.0 之前, <literal>final</literal> 和 <literal>static</literal>
的限制会应用于 private 方法。
从 PHP 8.0.0 开始,仅 <literal>private final</literal> 的构造器是唯一受限的 private 方法;
想要“禁用”构造器,我们通常用静态工厂方法作为代替。
</para>
<para>
方法,属性和常量的 <link linkend="language.oop5.visibility">可见性</link>
可以放宽,例如 <literal>protected</literal> 方法可以标记为 <literal>public</literal>,
但不能增加限制,例如标记 <literal>public</literal> 属性为 <literal>private</literal>。有个例外是构造方法,可以限制其可见性,例如
<literal>public</literal> 构造方法可以在子类中标记为 <literal>private</literal>。
</para>
<note>
<para>
除非使用了自动加载,否则一个类必须在使用之前被定义。如果一个类扩展了另一个,则父类必须在子类之前被声明。此规则适用于类继承其它类与接口。
</para>
</note>
<note>
<para>
不允许使用<link linkend="language.oop5.properties.readonly-properties">只读属性</link>覆盖可读写属性,反之亦然。
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
class A {
public int $prop;
}
class B extends A {
// Illegal: read-write -> readonly
public readonly int $prop;
}
?>
]]>
</programlisting>
</informalexample>
</para>
</note>
<example>
<title>继承示例</title>
<programlisting role="php">
<![CDATA[
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
public function printPHP()
{
echo 'PHP is great.' . PHP_EOL;
}
}
class Bar extends Foo
{
public function printItem($string)
{
echo 'Bar: ' . $string . PHP_EOL;
}
}
$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // 输出: 'Foo: baz'
$foo->printPHP(); // 输出: 'PHP is great'
$bar->printItem('baz'); // 输出: 'Bar: baz'
$bar->printPHP(); // 输出: 'PHP is great'
?>
]]>
</programlisting>
</example>
<sect2 xml:id="language.oop5.inheritance.internal-classes">
<title>返回类型与内部类兼容</title>
<para>
PHP 8.1 之前,大多数内部类或方法没有声明其返回类型,并且在继承它们时允许返回任何类型。
</para>
<para>
自 PHP 8.1.0 起,大多数内部方法开始“暂时”声明其返回类型,在这种情况下,方法的返回类型应该与继承的父级方法兼容;否则,将发出弃用通知。注意,没有指定返回声明也会视为签名不匹配,从而导致弃用通知。
</para>
<para>
如果由于 PHP 跨版本兼容性问题而无法为重写方法声明返回类型,则可以添加 <classname>ReturnTypeWillChange</classname> 注解来消除弃用通知。
</para>
<example>
<title>The overriding method does not declare any return type</title>
<programlisting role="php">
<![CDATA[
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier) { return false; }
}
// "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
?>
]]>
</programlisting>
</example>
<example>
<title>The overriding method declares a wrong return type</title>
<programlisting role="php">
<![CDATA[
<?php
class MyDateTime extends DateTime
{
public function modify(string $modifier): ?DateTime { return null; }
}
// "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
?>
]]>
</programlisting>
</example>
<example>
<title>The overriding method declares a wrong return type without a deprecation notice</title>
<programlisting role="php">
<![CDATA[
<?php
class MyDateTime extends DateTime
{
/**
* @return DateTime|false
*/
#[\ReturnTypeWillChange]
public function modify(string $modifier) { return false; }
}
// No notice is triggered
?>
]]>
</programlisting>
</example>
</sect2>
</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->