teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

b

2018/12/11 18:52

投稿

papinianus
papinianus

スコア12705

answer CHANGED
@@ -1,4 +1,66 @@
1
1
  staticと、static::は別物です。
2
2
 
3
3
  static::もparent::もクラスを返します。
4
- $this->の代わりにself::としても動作します。
4
+ $this->の代わりにself::としても動作します。
5
+
6
+ ---
7
+ 改めて。
8
+ [スコープ定義演算子 (::) ](https://secure.php.net/manual/ja/language.oop5.paamayim-nekudotayim.php)のマニュアルの
9
+ > 「ダブルコロン」は、トークンのひとつです。 static, 定数 およびオーバーライドされたクラスのプロパティやメソッドにアクセスすることができます。
10
+
11
+ の「オーバーライドされたクラスのプロパティやメソッド」の部分は正確でないのではないかと考えるに至りました。
12
+ マニュアル自身、[クラスの基礎](https://secure.php.net/manual/ja/language.oop5.basic.php#language.oop5.basic.class.this)の「例2 $this 疑似変数の例」において、`A::foo();`という書き方で、クラスAのstaticでもオーバーライドされてもいないメソッドfooにアクセスする例を書いてます。
13
+ プロパティについて言えば逆にオーバーライドしていてもstaticでないと`parent::`によって参照することができませんでした。
14
+ ```php
15
+ <?php
16
+ class A {
17
+ public function a() { return 1; }
18
+ public $a1 = "prop";
19
+ }
20
+ class B extends A {
21
+ public function b() { return parent::a(); }
22
+ public function b1() { return parent::$a1; } //PHP Fatal error: Uncaught Error: Access to undeclared static property: A::$a1
23
+ public $a1 = "new";
24
+ }
25
+ ```
26
+
27
+ 現在の私の理解としては
28
+ > 「ダブルコロン」は、トークンのひとつです。 「定数」または「staticなクラスのプロパティ」、「クラスのメソッド」にアクセスすることができます。
29
+
30
+ ではないかと思います。
31
+ また、質問者様ご提示のような書き方をしたときに(parent->でなく)`parent::`で動作する理由のもう一つとして、$this疑似変数が、(呼ばれ方にかかわらず)呼び出し元のオブジェクト指すことも影響しています。`parent::getName()`として、AのgetNameが呼ばれたときその関数本体の中で使われる$thisは、`->`を使っていないにもかかわらず、getNameを呼んだ(Aのサブクラスの)インスタンスを適切に指してくれます。詳しくは、上に引用した"クラスの基礎"の説明および例をご参照ください。
32
+
33
+
34
+ こう書いてしまうとやや余談になりますが、先に書いたself::についてはこれもstaticでない自クラスのメソッドを($this->でなくself::で)呼べるという意図でした。下記のパターンもご参考としていただければと思います。
35
+ ```php
36
+ class A {
37
+ public function a() { return 1; }
38
+ }
39
+ class B extends A {
40
+ public function b() { return parent::a(); }
41
+ }
42
+ class C extends A {
43
+ public function c() { return A::a(); }
44
+ }
45
+ class D extends A {
46
+ public function d() { return $this->a(); }
47
+ }
48
+ class E extends A {
49
+ public function e() { return self::a(); }
50
+ }
51
+ // class F {
52
+ // public function f() { return A::a(); } //fatal error
53
+ // }
54
+ $b = new B();
55
+ $c = new C();
56
+ $d = new D();
57
+ $e = new E();
58
+ //$f = new F();
59
+ // A::a(); // fatal error
60
+ var_dump($b->b());
61
+ var_dump($b->b1());
62
+ var_dump($c->c());
63
+ var_dump($d->d());
64
+ var_dump($e->e());
65
+ //var_dump($f->f());
66
+ ```