サブクラスから parent::
で親クラスのインスタンスメソッド、静的メソッドの両方にアクセスできます。
<?php class A { protected $firstName; protected $lastName; public function getName($args1, $args2) { $this->firstName = $args1; $this->lastName = $args2; echo $this->firstName . $this->lastName; } protected static $staticFirstName; protected static $staticLastName; public static function getStaticName($args1, $args2) { self::$staticFirstName = $args1; self::$staticLastName = $args2; echo self::$staticFirstName . self::$staticLastName; } } class B extends A { public function hoge($args1, $args2) { parent::getName($args1, $args2); } public function fuga($args1, $args2) { parent::getStaticName($args1, $args2); } } $b = new B(); $b->hoge('武蔵','宮本'); // 武蔵宮本 $b->fuga('小次郎','佐々木'); // 小次郎佐々木
これが腑に落ちません。
インスタンス、静的という考え方に誤りがあるのでしょうか。
static
のあるプロパティとメソッドはクラスに属することになり、スコープ定義演算子 ::
でアクセスします。(インスタンス化なしでアクセスできる)
static
のないプロパティとメソッドはインスタンスに属することになり、アロー演算子 ->
でアクセスします。
上記のように私の中では理解しております。
親クラスのインスタンスメソッドにアクセスするなら parent->
、静的メソッドにアクセスするなら parent::
という記述なら腹落ちしますが、parent::
でインスタンスメソッドと静的メソッドの両方にアクセスできることが腑に落ちません。
なぜ、parent::
で親クラスのインスタンスメソッドと静的メソッドの両方にアクセスできるのでしょうか?
私が根本的に誤って理解しているのかと思います。
どこに誤りがあるのか教えてください((_ _ (´ω` )
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答2件
0
サブクラスから parent:: で親クラスのインスタンスメソッド、静的メソッドの両方にアクセスできます。
違うなぁ。混乱しやすいのかもしれないけど。
インスタンス(動的プロパティ、動的メソッド)にアクセスするのはアロー演算子、
クラス(静的プロパティ、静的メソッド)にアクセスするのがダブルコロン。
お約束のリファレンスより。
PHP: スコープ定義演算子 (::) - Manual
self:: で自クラスのプロパティ、静的メソッドにアクセスできる。
parent:: で親クラスのプロパティ、静的メソッドにアクセスできる。
public 宣言されたクラスのメンバーには、どこからでもアクセス可能です。
protected 宣言されたメンバーには、 そのクラス自身、そのクラスを継承したクラス、および親クラスからのみアクセスできます。
private 宣言されたメンバーには、そのメンバーを定義したクラスからのみアクセスできます。
クラスプロパティもしくはメソッドを static として宣言することで、 クラスのインスタンス化の必要なしにアクセスすることができます。 static なプロパティは、インスタンス化されたクラスオブジェクトから アクセスすることはできません (static なメソッドにはアクセスできます)。
クラスを拡張するとき、サブクラスは親クラスから public と、protected のメソッドをすべてを引き継ぎます。
すっごく時間をかけて説明文を書いてみたけど、
説明が危うく拙い気がしたので、消して、
もうちょっとわかりやすい記事を探してみた。
PHPを愛する試み 〜self:: parent:: static:: および遅延静的束縛〜 - maeharinの日記
PHPの「$this」と「self::」の違い - Qiita
検証コードを書きながら、
親クラスからの継承の話と、
おなじ命名空間での他クラスからのアクセスの話も知っといたほうがいいと思えてきました。
謎なコードを示します。
php
1<?php 2 3class foo { 4 public function hoge() { echo 'hoge'; } 5 public static function fuga() { echo 'fuga'; } 6} 7 8class bar { 9 public function piyo() { 10 echo foo::hoge(); 11 } 12} 13$x = new bar(); 14$x->piyo();
これ、実行すると、
「Deprecated: Non-static method foo::hoge() should not be called statically」
ってエラーメッセージが出ますが、
「hoge」って出力されます。
php
1class bar { 2 public function piyo() { 3 echo foo::fuga(); 4 } 5}
とすることでエラーメッセージなしに「fuga」って出力されます。
クラスfooとbarの間には継承の関係はありません。
同じ命名空間にいるだけです。
php
1<?php 2 3class foo { 4 public const X = 1; 5 public static $y = 2; // staticがないとFatal error 6} 7 8class bar { 9 public function piyo() { 10 echo foo::X . PHP_EOL; 11 echo foo::$y . PHP_EOL; 12 } 13} 14$x = new bar(); 15$x->piyo();
結果は「1(改行)2(改行)」です。
クラスうんぬんいうまえに、スコープ演算子と命名空間のことも知っとかないと、
危ういと思います。
(これが理解できると、フレームワークのソースコードも読めるようになるのかも。)
投稿2018/12/11 10:41
編集2018/12/12 01:53
退会済みユーザー
総合スコア0
0
ベストアンサー
staticと、static::は別物です。
static::もparent::もクラスを返します。
$this->の代わりにself::としても動作します。
改めて。
スコープ定義演算子 (::) のマニュアルの
「ダブルコロン」は、トークンのひとつです。 static, 定数 およびオーバーライドされたクラスのプロパティやメソッドにアクセスすることができます。
の「オーバーライドされたクラスのプロパティやメソッド」の部分は正確でないのではないかと考えるに至りました。
マニュアル自身、クラスの基礎の「例2 $this 疑似変数の例」において、A::foo();
という書き方で、クラスAのstaticでもオーバーライドされてもいないメソッドfooにアクセスする例を書いてます。
プロパティについて言えば逆にオーバーライドしていてもstaticでないとparent::
によって参照することができませんでした。
php
1<?php 2class A { 3 public function a() { return 1; } 4 public $a1 = "prop"; 5} 6class B extends A { 7 public function b() { return parent::a(); } 8 public function b1() { return parent::$a1; } //PHP Fatal error: Uncaught Error: Access to undeclared static property: A::$a1 9 public $a1 = "new"; 10}
現在の私の理解としては
「ダブルコロン」は、トークンのひとつです。 「定数」または「staticなクラスのプロパティ」、「クラスのメソッド」にアクセスすることができます。
ではないかと思います。
また、質問者様ご提示のような書き方をしたときに(parent->でなく)parent::
で動作する理由のもう一つとして、$this疑似変数が、(呼ばれ方にかかわらず)呼び出し元のオブジェクト指すことも影響しています。parent::getName()
として、AのgetNameが呼ばれたときその関数本体の中で使われる$thisは、->
を使っていないにもかかわらず、getNameを呼んだ(Aのサブクラスの)インスタンスを適切に指してくれます。詳しくは、上に引用した"クラスの基礎"の説明および例をご参照ください。
こう書いてしまうとやや余談になりますが、先に書いたself::についてはこれもstaticでない自クラスのメソッドを($this->でなくself::で)呼べるという意図でした。下記のパターンもご参考としていただければと思います。
php
1class A { 2 public function a() { return 1; } 3} 4class B extends A { 5 public function b() { return parent::a(); } 6} 7class C extends A { 8 public function c() { return A::a(); } 9} 10class D extends A { 11 public function d() { return $this->a(); } 12} 13class E extends A { 14 public function e() { return self::a(); } 15} 16// class F { 17// public function f() { return A::a(); } //fatal error 18// } 19$b = new B(); 20$c = new C(); 21$d = new D(); 22$e = new E(); 23//$f = new F(); 24// A::a(); // fatal error 25var_dump($b->b()); 26var_dump($b->b1()); 27var_dump($c->c()); 28var_dump($d->d()); 29var_dump($e->e()); 30//var_dump($f->f());
投稿2018/12/11 09:34
編集2018/12/11 18:52総合スコア12705
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/12/11 11:18
2018/12/11 19:09
退会済みユーザー
2018/12/12 00:38
退会済みユーザー
2018/12/12 00:46
2018/12/12 01:00 編集
退会済みユーザー
2018/12/12 01:52
2018/12/12 07:53
退会済みユーザー
2018/12/12 08:03
2018/12/13 02:35 編集