-
Notifications
You must be signed in to change notification settings - Fork 79
/
Copy pathabstract.xml
241 lines (210 loc) · 6.62 KB
/
abstract.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- EN-Revision: 984188eb6941dc419f49eed6c1a55a6b749a823d Maintainer: hirokawa Status: ready -->
<!-- CREDITS: shimooka -->
<sect1 xml:id="language.oop5.abstract" xmlns="http://docbook.org/ns/docbook">
<title>クラスの抽象化</title>
<para>
PHP には、抽象クラス、抽象メソッド、抽象プロパティがあります。
abstract として定義された抽象クラスのインスタンスを生成することはできず、
1つ以上の抽象メソッドや抽象プロパティを含むクラスは抽象クラスでなければいけません。
abstract として定義されたメソッドは、そのメソッドのシグネチャと public または protected のアクセス権を宣言するのみで、
実装を定義することはできません。抽象プロパティは、
<literal>get</literal> や <literal>set</literal> の要件を宣言することができ、
実装はどちらか一方に対してのみ行えます。両方同時に実装することはできません。
</para>
<para>
抽象クラスから継承する際、親クラスの宣言で abstract としてマークされた
全てのメソッドは、子クラスで定義されなければなりません。加えて、
<link linkend="language.oop5.inheritance">オブジェクトの継承</link> と
<link linkend="language.oop.lsp">シグネチャの互換性に関するルール</link> に従わなければいけません。
</para>
<simpara>
PHP 8.4 から、抽象クラスは public または protected の抽象プロパティを宣言できるようになりました。
protected な抽象プロパティは、protected または public のスコープから読み書き可能なプロパティにより
要件が満たされます。
</simpara>
<simpara>
抽象プロパティは、通常のプロパティによって、または
必要な操作に対応した <link linkend="language.oop5.property-hooks">フック</link> を定義したプロパティにより要件が満たされます。
</simpara>
<example>
<title>抽象メソッドの例</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class AbstractClass
{
// 拡張クラスにこのメソッドの定義を強制する
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Common method
public function printOut()
{
print $this->getValue() . "\n";
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue()
{
return "ConcreteClass1";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue()
{
return "ConcreteClass2";
}
public function prefixValue($prefix)
{
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1();
$class1->printOut();
echo $class1->prefixValue('FOO_'), "\n";
$class2 = new ConcreteClass2();
$class2->printOut();
echo $class2->prefixValue('FOO_'), "\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
]]>
</screen>
</example>
<example>
<title>抽象メソッドの例</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class AbstractClass
{
// 抽象メソッドでは、必須の引数だけを定義しています
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// 子クラスでは、親のシグネチャにないオプション引数を定義することもあるでしょう
public function prefixName($name, $separator = ".")
{
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass();
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Mr. Pacman
Mrs. Pacwoman
]]>
</screen>
</example>
<example>
<title>抽象プロパティの例</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class A
{
// 継承するクラスは、public に読み取り可能なプロパティを持たなければなりません
abstract public string $readable {
get;
}
// 継承するクラスは、protected または public に書き込み可能なプロパティを持たなければなりません
abstract protected string $writeable {
set;
}
// 継承するクラスは、protected または public で読み書き可能なプロパティを持たなければなりません
abstract protected string $both {
get;
set;
}
}
class C extends A
{
// 要件を満たし、さらに書き込みも可能にしているため有効です
public string $readable;
// public に読み取り可能でないため、要件を満たしません
protected string $readable;
// 要件を正確に満たしているため有効です
// protected のスコープからのみ書き込みが可能です
protected string $writeable {
set => $value;
}
// protected から public にアクセス権を拡張しており、問題ありません
public string $both;
}
?>
]]>
</programlisting>
</example>
<simpara>
抽象プロパティにはフックを実装できます。
前の例のように、<literal>get</literal> または <literal>set</literal> のどちらかを、定義せず宣言のみ行います。
</simpara>
<example>
<title>抽象プロパティの例</title>
<programlisting role="php">
<![CDATA[
<?php
abstract class A
{
// set のデフォルト実装(オーバーライド可能)を提供し、
// 子クラスが get を実装するよう要求しています
abstract public string $foo {
get;
set {
$this->foo = $value;
}
}
}
?>
]]>
</programlisting>
</example>
</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
-->