質問: new B(); $b->hoge('武蔵','宮本'); // 武蔵宮本 $b->fuga('小次郎','佐々木'); // 小次郎佐々木 ``` これが腑に落ちません。 インスタンス、静的という考え方に誤りがあるのでしょうか。 `static` のあるプロパティとメソッドはクラスに属することになり、スコープ定義演算子 `::` でアクセスします。(インスタンス化なしでアクセスできる) `static` のないプロパティとメソッドはインスタンスに属することになり、アロー演算子 `->` でアクセスします。 上記のように私の中では理解しております。 親クラスのインスタンスメソッドにアクセスするなら `parent->` 、静的メソッドにアクセスするなら `parent::` という記述なら腹落ちしますが、`parent::` でインスタンスメソッドと静的メソッドの両方にアクセスできることが腑に落ちません。 なぜ、`parent::` で親クラスのインスタンスメソッドと静的メソッドの両方にアクセスできるのでしょうか? 私が根本的に誤って理解しているのかと思います。 どこに誤りがあるのか教えてください((_ _ ( ́ω` )
回答: staticと、static::は別物です。 static::もparent::もクラスを返します。 $this->の代わりにself::としても動作します。 改めて。 スコープ定義演算子 (::)のマニュアルの > > 「ダブルコロン」は、トークンのひとつです。 static, 定数 およびオーバーライドされたクラスのプロパティやメソッドにアクセスすることができます。 > > > の「オーバーライドされたクラスのプロパティやメソッド」の部分は正確でないのではないかと考えるに至りました。 マニュアル自身、クラスの基礎の「例2 $this 疑似変数の例」において、`A::foo();`という書き方で、クラスAのstaticでもオーバーライドされてもいないメソッドfooにアクセスする例を書いてます。 プロパティについて言えば逆にオーバーライドしていてもstaticでないと`parent::`によって参照することができませんでした。 ``` > 「ダブルコロン」は、トークンのひとつです。 「定数」または「staticなクラスのプロパティ」、「クラスのメソッド」にアクセスすることができます。 > > > ではないかと思います。 また、質問者様ご提示のような書き方をしたときに(parent->でなく)`parent::`で動作する理由のもう一つとして、$this疑似変数が、(呼ばれ方にかかわらず)呼び出し元のオブジェクト指すことも影響しています。`parent::getName()`として、AのgetNameが呼ばれたときその関数本体の中で使われる$thisは、`->`を使っていないにもかかわらず、getNameを呼んだ(Aのサブクラスの)インスタンスを適切に指してくれます。詳しくは、上に引用した"クラスの基礎"の説明および例をご参照ください。 こう書いてしまうとやや余談になりますが、先に書いたself::についてはこれもstaticでない自クラスのメソッドを($this->でなくself::で)呼べるという意図でした。下記のパターンもご参考としていただければと思います。 ``` 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()); ```