回答編集履歴

1 b

papinianus

papinianus score 9087

2018/12/12 03:52  投稿

staticと、static::は別物です。
static::もparent::もクラスを返します。
$this->の代わりにself::としても動作します。
$this->の代わりにself::としても動作します。
---
改めて。
[スコープ定義演算子 (::) ](https://secure.php.net/manual/ja/language.oop5.paamayim-nekudotayim.php)のマニュアルの
> 「ダブルコロン」は、トークンのひとつです。 static, 定数 およびオーバーライドされたクラスのプロパティやメソッドにアクセスすることができます。
の「オーバーライドされたクラスのプロパティやメソッド」の部分は正確でないのではないかと考えるに至りました。
マニュアル自身、[クラスの基礎](https://secure.php.net/manual/ja/language.oop5.basic.php#language.oop5.basic.class.this)の「例2 $this 疑似変数の例」において、`A::foo();`という書き方で、クラスAのstaticでもオーバーライドされてもいないメソッドfooにアクセスする例を書いてます。
プロパティについて言えば逆にオーバーライドしていてもstaticでないと`parent::`によって参照することができませんでした。
```php
<?php
class A {
   public function a() { return 1; }
   public $a1 = "prop";
}
class B extends A {
   public function b() { return parent::a(); }
   public function b1() { return parent::$a1; } //PHP Fatal error: Uncaught Error: Access to undeclared static property: A::$a1
   public $a1 = "new";
}
```
現在の私の理解としては
> 「ダブルコロン」は、トークンのひとつです。 「定数」または「staticなクラスのプロパティ」、「クラスのメソッド」にアクセスすることができます。
ではないかと思います。
また、質問者様ご提示のような書き方をしたときに(parent->でなく)`parent::`で動作する理由のもう一つとして、$this疑似変数が、(呼ばれ方にかかわらず)呼び出し元のオブジェクト指すことも影響しています。`parent::getName()`として、AのgetNameが呼ばれたときその関数本体の中で使われる$thisは、`->`を使っていないにもかかわらず、getNameを呼んだ(Aのサブクラスの)インスタンスを適切に指してくれます。詳しくは、上に引用した"クラスの基礎"の説明および例をご参照ください。
こう書いてしまうとやや余談になりますが、先に書いたself::についてはこれもstaticでない自クラスのメソッドを($this->でなくself::で)呼べるという意図でした。下記のパターンもご参考としていただければと思います。
```php
class A {
   public function a() { return 1; }
}
class B extends A {
   public function b() { return parent::a(); }
}
class C extends A {
   public function c() { return A::a(); }
}
class D extends A {
   public function d() { return $this->a(); }
}
class E extends A {
   public function e() { return self::a(); }
}
// class F {
//    public function f() { return A::a(); } //fatal error
// }
$b = new B();
$c = new C();
$d = new D();
$e = new E();
//$f = new F();
// A::a(); // fatal error
var_dump($b->b());
var_dump($b->b1());
var_dump($c->c());
var_dump($d->d());
var_dump($e->e());
//var_dump($f->f());
```

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る