回答編集履歴

1

回答へのコメントを受けて、回答内容追加

2019/02/01 05:40

投稿

nak
nak

スコア696

test CHANGED
@@ -191,3 +191,159 @@
191
191
  ↓静的遅延束縛のマニュアル
192
192
 
193
193
  http://php.net/manual/ja/language.oop5.late-static-bindings.php
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
+ ・static メソッド=静的メソッド(staticの日本語訳が"静的"なので)
226
+
227
+ ・非static メソッド=静的ではないメソッド≒動的メソッド
228
+
229
+
230
+
231
+ です。
232
+
233
+
234
+
235
+ そして、この「静的メソッド」と「動的メソッド」というのは、PHP独自の概念ではなく、オブジェクト指向型言語全般(Java、C、等々)に一般的に存在する概念である、ということはご理解ください。
236
+
237
+
238
+
239
+ 解説ページ(PHPのページではありませんが、わかりやすくまとまっていたのでご紹介です)
240
+
241
+ https://yryr.me/programming/csharp/beginner/object-model/object-model-static-dynamic-difference.html
242
+
243
+
244
+
245
+ そして、ここで「(メソッドを)静的にコールする(calling methods statically)」と書かれているのは、超意訳すると「静的(メソッドを、静的メソッドを呼び出すために用意された方法で)コールする」ということになるかと思います。
246
+
247
+
248
+
249
+ 以上の内容を踏まえ、具体的なご質問への回答です。
250
+
251
+
252
+
253
+
254
+
255
+ > 「静的にコールする」=「クラスオブジェクト(インスタンス)を作らずに直接メソッドを呼ぶ」ということでしょうか?
256
+
257
+
258
+
259
+ はい、本質的なところはそのとおりです(上記解説ページ参照のこと)。
260
+
261
+
262
+
263
+ そして、通常は
264
+
265
+
266
+
267
+ > 「::(スコープ定義演算子)を用いてメソッドを呼び出すこと」を「静的にコールする」と認識していました。
268
+
269
+
270
+
271
+ という認識でも問題ないはずでした(スコープ演算子を用いてメソッドを呼び出す≒クラスオブジェクト(インスタンス)を作らずに直接メソッドを呼ぶために定義された書式がほとんどなので)。
272
+
273
+
274
+
275
+ が、「スコープ定義演算子を用いてメソッドを呼び出す([クラス名]::、self::、parent::、static::)」もののうち、「static::」のみ特殊な挙動をします(詳細は後述)。
276
+
277
+
278
+
279
+
280
+
281
+ > それで考えると、質問のコードではCのインスタンスを作ってtest()を呼び出している→そのtest()で
282
+
283
+ static::foo()を呼び出している。
284
+
285
+ > 遅延静的束縛によりstaticはCクラスを指す、Cのインスタンスを作っているから、このstatic::foo()は
286
+
287
+ 静的なコールではない、ということでしょうか?
288
+
289
+
290
+
291
+ 結論が「静的なコールではない」というのは正しいのですが、その理由は、「Cのインスタンスを作っているから」ではありません。
292
+
293
+
294
+
295
+ 遅延静的束縛のマニュアルに、下記の記載があります。
296
+
297
+
298
+
299
+ > 静的メソッドの場合、これは明示的に指定されたクラス (通常は :: 演算子の左側に書かれたもの) となります。
300
+
301
+ > 静的メソッド以外の場合は、そのオブジェクトのクラスとなります。
302
+
303
+
304
+
305
+ これを把握した上で、改めて、fooメソッドの宣言部分を見てみましょう。
306
+
307
+
308
+
309
+ ```
310
+
311
+ private function foo()
312
+
313
+ ```
314
+
315
+
316
+
317
+ メソッドの宣言に"static"が付いていません。
318
+
319
+ つまり、これは「静的メソッド以外」ということになります。
320
+
321
+
322
+
323
+ 今回は、「静的メソッド以外から、static::を使ってfoo()メソッドが呼ばれた」ので「そのオブジェクトのクラス」のメソッドが動的に呼ばれたのです。
324
+
325
+
326
+
327
+ ```
328
+
329
+ スコープ演算子を使ってメソッドを呼び出した時の動的・静的の違い
330
+
331
+
332
+
333
+   ・"static::"
334
+
335
+     ・呼出し先メソッドが静的でも動的でも使用できる
336
+
337
+     ・呼出し先メソッドの定義(静的メソッドか動的メソッドか)によって、静的なコールか動的なコールかが変わる
338
+
339
+
340
+
341
+   ・"[クラス名]::"、"self::"、"parent::"
342
+
343
+     ・呼出し先メソッドが静的な場合しか使用できない
344
+
345
+     ・必ず静的なコールになる(静的メソッドは静的なコールしかできないので)
346
+
347
+
348
+
349
+ ```