PHPでの継承について

このQ&Aのポイント
  • PHPの継承についての質問です。
  • PHPではクラスを継承する場合、スーパークラスのpublicとprotectedなメンバを継承します。
  • 継承とは、スーパークラスで定義したメンバがサブクラスで定義されたことと同義ですが、実行時エラーが発生しています。
回答を見る
  • ベストアンサー

PHPでの継承について

PHPの継承についての質問です。 PHPではクラスを継承する場合 スーパークラスのpublicとprotectedなメンバを継承すると いいます。 継承とは、スーパークラスで定義したメンバが サブクラスで定義されたことと同義である。 という前提で質問します。 ひょっとしたらこの前提も微妙に間違っているかもしれません。 以下の用なコードがあるとします。 <?php class AClass { //サブクラスへ継承されるスーパークラスのメソッド public function superClassPublicMethod(){ //【1】 $this-> subClassPrivateMethod(); } } class BClass extends AClass{ public function subClassPublicMethod(){//【2】 $this->subClassPrivateMethod(); } //継承したスーパークラスで定義されているメソッドからコールするサブクラスで定義したメソッド private function subClassPrivateMethod(){ //【3】 print __CLASS__; } } $obj = new BClass(); //サブクラスで定義した public なメソッドを実行 $obj->subClassPublicMethod(); //【4】 //スーパークラスから継承したpublic なメソッドを実行 $obj-> superClassPublicMethod();//【5】 ?> コレを実行すると【4】はきちんとBClassという結果が返ってきます。 ところがその下の【5】を実行すると Fatal error: Call to private method BClass::subClassPrivateMethod() from context 'AClass' in /usr/local/apache/htdocs/ext06.php on line 9 という実行時エラーが返ってきます。これを読むと、AClassのコンテキスト内ではBClassのprivateなメンバは コールできませんよ。というエラーですね。そもそもAClassのコンテキストということは、これはAClass内で実行されているということですよね? ここで、スーパークラスからこのpublicなメソッドは継承しているはずなのになぜ、サブクラスのBCLass内ではなくスーパークラスのAClass内という エラーが返っているのでしょうか? 継承とは、サブクラスで定義したと同義ではなく、スーパークラスまで内部的にアップキャスト?してコールしにいっているのでしょうか? 詳しい方ご教授ください。 よろしく御願いします。

  • PHP
  • 回答数2
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

> とありますが、つまり意味合い的には、いくらクラスを継承しても、 > メソッドやプロパティ自体が物理的に(こういう表現でいいかわかりませんが)サブクラス内に引き継が > れることはなく > オーバ-ライドしない限りは、メソッドはスーパークラス内に存在しているままということでしょうか? んと、引き継がれはします。継承ですから。 引き継がれる=コピーされるのではない、と言えば分かりいいかもしれません。 オーバーライドしていないならば、実体はあくまでAClass内に存在しているわけです。 デバッグ実行をすれば一番分かりやすいと思いますよ。 superClassPublicMethod()を呼び出した瞬間、BClassではなくAClassへ制御が移ります。 > いろいろなサイトではまるで継承することによって > public・protectedなメンバが無条件でサブクラスの物になるように描かれているので・・・・・。 オーバーライドしなければサブクラスの物にはなりません。 正確には、オーバーライドしてもサブクラスのものにはなりません。 なぜなら、サブクラス内でこういうことが出来ますので。 class BClass extends AClass {  public function superClassPublicMethod() {   parent::superClassPublicMethod(); //AClass::superClassPublicMethod()が呼び出される  } } $obj = new BClass(); $obj->subClassPublicMethod(); $obj->superClassPublicMethod(); //BClass::superClassPublicMethod()が呼び出される

__vicky__
質問者

お礼

二度目の回答ありがとうございました。 なんとか、継承理解の糸口がつかめた感じです。

その他の回答 (1)

回答No.1

ええ、なぜならAClass::superClassPublicMethod()を呼んでますからね。 superClassPublicMethod()はAClassのメンバであって、BClassのメンバではありません。 それをしたいならば、それこそ継承しているわけですから、BClass内で superClassPublicMethod()をオーバーライドしてコードします。 継承してオーバーライドしなかったメンバは、自動的にサブクラスに展開されるのではなく、 スーパークラスへ遡って処理されます。 また、例で挙げているだけでご存知だと思いますが、スーパークラスが 暗黙的に、更には前提であるかのように、サブクラスに依存するような コードを書くことは普通しません。 やる場合はインターフェースや抽象メソッドを用意して実装します。

__vicky__
質問者

お礼

ご回答ありがとうございます。 まず、例にあげた、コードですがあくまで継承時のメソッドの動きを検証するためのものです。先に、その旨を描くべきでしたね。 すいません。 一点、 >継承してオーバーライドしなかったメンバは、自動的にサブクラスに展開されるのではなく、 スーパークラスへ遡って処理されます。 とありますが、つまり意味合い的には、いくらクラスを継承しても、 メソッドやプロパティ自体が物理的に(こういう表現でいいかわかりませんが)サブクラス内に引き継がれることはなく オーバ-ライドしない限りは、メソッドはスーパークラス内に存在しているままということでしょうか? いろいろなサイトではまるで継承することによって public・protectedなメンバが無条件でサブクラスの物になるように描かれているので・・・・・。

関連するQ&A

  • PHPでサブクラスからスーパクラスのprivate

    メンバにアクセスできる件について PHPでスーパークラスで定義したprivateのメンバにサブクラスからアクセスできる件について 質問です。 class TestClass { private $value01 = "スーパークラスの private メンバ"; public function testMethod01 () { print "スーパークラスのパブリックメソッド"; print "<h1>{$this->value01}</h1>"; } protected function testMethod02(){ print "スーパークラスの protected メソッド"; } private function testMethod03(){ print "スーパークラスの private メソッド"; } public function getMethodList(){ print_r(get_class_methods($this)); } } class ExClass extends TestClass{ private $value01 = "サブクラスの private メンバ"; } $obj = new ExClass(); $obj-> testMethod01(); と上記のようにサブクラスのインスタンスから継承したpublicなメソッド testMethod01()を実行すると スーパークラスのprivateなプロパティにアクセスできてしまいます。 これってどういうことでしょうか?privateメンバってそのクラスの中からだけしかアクセスできませんよね? 上記では、サブクラスからアクセスしているような状態にみえますがどういうことでしょうか? ご教授御願い致します。

    • ベストアンサー
    • PHP
  • 継承について

    下の質問の回答、間違ってませんか? -------------------------------------------- 親クラスのフィールドをメソッドを全て継承することになります。よって、サブクラス2は、サブクラス1とスーパークラスのメンバーを全て持つことになります。サブクラス2をインスタンス化すると、サブクラス1とスーパークラスが全てインスタンス化(コンピューターのメモリ上等に配置)されます。 ただ、可視性というものがあり、サブクラスから親クラスのメンバーを直接取り扱えない場合があります。privateや可視性修飾子無しの場合、サブクラスから直接取り扱えません。ただ、継承はされているので、インスタンスとしては存在します。例えば、 class スーパークラス{ private int abc; public int getAbc(){ return this.abc; } というクラスがあり、これを継承したサブクラスがあったとします。 サブクラスからは、privateなメンバー変数abcは直接取り扱うことができません。ただ、publicなgetAbcメソッドはサブクラスから取り扱えます。これで何が分かるかといいますと、privateなメンバーでもサブクラスに継承されるのです。単に可視性の問題で直接取り扱えないだけなのです。 また、オーバーライドされたメソッドがあったとしても、super.メソッド()で親のメソッドも呼べますので、これも継承されているのです。

  • 継承(extends)について

    extendsについてわからないことがあります。 次の3つのクラスがあった時、 class スーパークラス { ... class サブクラス1 extends スーパークラス { ... class サブクラス2 extends サブクラス1 {... サブクラス2は、サブクラス1でスーパークラスから継承しているフィールドをメソッドを継承するのでしょうか?

    • ベストアンサー
    • Java
  • PHPのクラス継承において質問

    class SuperClass{ public function getSuperClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } } class SubClass extends SuperClass{ public function getSubClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } $obj = new SubClass(); print "<br />"; $obj -> getSuperClassName(); print "<br />"; $obj -> getSubClassName(); 上記のようなコードがあった場合、 出力結果は SubClass SuperClass //継承しているにもかかわらず、SuperClassという文字列が返る。 SubClass SubClass と上記のようになります この結果に一点疑問があるのですが、親クラスのメソッドは子クラスに継承されるんですよね? であれば親クラスの public function getSuperClassName (){ //操作中のオブジェクトのクラス名を取得する print get_class($this); print "<br />"; print __CLASS__; } の箇所の print __CLASS__; の記述箇所はSubClassとでなければいけないような気がします。 しかし結果はSuperClassとでますが、このメソッドは子クラスに継承されていないのですか? publicなら継承されるとマニュアルにかいてありましたが、どうなっているのでしょうか よろしくご教授御願い致します。

    • ベストアンサー
    • PHP
  • JAVA初心者です。

    javaにおけるprivateメンバの動きについて伺いたいことがございます。 基本的にスーパークラスのprivateなメンバへはメソッド・フィールドともにサブクラスからは アクセスできないとのことですが、 例えば、以下のようなコードがあるとします。 //スーパークラスの定義 class SuperClass{ private String privateString = "スーパークラスのプライベートメンバ"; public void getter(){ System.out.println(this.privateString); } } //サブクラス class SubClass extends SuperClass{ } //実行クラス class RunClass { static public void main (String args []){ SubClass subObj; subObj = new SubClass(); subObj.getter(); } } 上記のようなコードの場合サブクラスのインスタンスであるsubObjが スーパークラスのpublicなメソッドを通じてサブクラスからスーパークラスのprivateメンバへアクセスが できてしまっています。 これは、スーパークラスのprivateが隠蔽されていないのではないでしょうか? 果たして、このときいったサブクラスのインスタンスのsubObjはどういった動きをしているのでしょうか?

    • ベストアンサー
    • Java
  • C#の継承関係。

    すこし、疑問におもい質問いたします。 以下のようなコードなのですが using System; using System.Windows.Forms; public class MainClass{ public static void Main (){ Test01 obj01 , obj02; Test02 obj03 , obj04; obj01= new Test01(); obj01.method01(); obj03 = new Test02(); obj03.method02(); try{ obj02 = (Test01)obj03;(1) //obj02.methodp();(2) obj04 = (Test02)obj01;(3) }catch(Exception e){ MessageBox.Show(e.Message); } } } public class Test01{ public void method01(){ MessageBox.Show("スーパークラスメソッド"); } private void methodp (){ MessageBox.Show("スーパークラスプライベートメソッド"); } } public class Test02 : Test01{ public void method02(){ MessageBox.Show("サブクラスメソッド"); } } まず(1)の箇所ですが、これはTest02というTest01のクラスを継承したサブクラスを Test01という親クラスにキャストしてます。 これは、問題なく動いているようです。 ただ、その下の(2)の箇所でキャストしたインスタンスから親クラスのプライベートメソッドにアクセスしようとしたらコンパイル時にエラーとなりました。 サブクラスを親クラスにしても親クラスのプライベートメソッドって使えないのでしょうか?であれば親クラスへのキャストって何のためにあるのでしょうか? 次に(3)の箇所ですが、これはTest01という親クラスをTest02という子クラスにキャストしようとしていますが、どうも、親クラスから子クラスへキャストできないといいう例外が 発生するようです。 これはなぜなのでしょうか? 以上の点でご教授いただけませんでしょうか? よろしくお願いします。

  • 【PHP】クラスを継承した際にデータ型も継承すると

    とある有料のオンライン学習サイトをつかっています。 学習項目の流れは以下の通りです。 現在「15 型の継承について見ていこう」で躓いています。 01 オブジェクトを使ってみよう (02:56) 02 投稿に関する処理を作ろう 03 クラスでデータ型を定義しよう 04 インスタンスを作ってみよう 05 コンストラクタを使ってみよう 06 クラスを整理しておこう 07 アクセス修飾子について見ていこう 08 メソッドを介してプロパティを操作しよう 09 プロパティで型宣言をしてみよう 10 staticキーワードを使ってみよう 11 オブジェクト定数を使ってみよう 12 クラスを継承してみよう 13 子クラスで独自の実装をしていこう 14 メソッドをoverrideしてみよう 15 型の継承について見ていこう *型の継承 *型を継承するメリット この項目で記述されているソースコードは下記のとおりです。コード内のクラス、SponsoredPostは クラスPostを継承しています。よって両方のクラスともにPost型として扱えると説明があります。 ソース内のこの箇所で processPostという関数を作成し、変数$postにPost型と型付けをしています そしてforeachでPostで型付けられた$post型(クラスPostとそれを継承したクラスSponsoredPost)をひとつづつ取り出し、processPostを用いてそれぞれにshow()メソッドで表示させています。 ----------------------- <?php class Post{ protected $text; public function __construct($text){ $this->text = $text; } public function show(){ printf('%s',$this->text); } class SponsoredPost extends Post{ private $sponsor; public function __construct($text, $sponsor){ parent::__construct($text); $this->sponsor = $sponsor; } public function show(){ printf('%s by %s', $this->text, $this->sponsor); } } $posts = []; $posts[0] = new Post('hello'); $posts[1] = new Post('hello again'); $posts[2] = new SponsoredPost('iPhone','Apple'); function processPost(Post $post){ $post->show(); } foreach($posts as $post){ processPost($post); ------------- クラスを継承すると親クラスのプロパティやメソッドが子クラスに継承されるというのは理解できています。「15 型の継承について見ていこう」という項目では 『Post型の変数を受け取る関数を作って、データ型が継承されることを説明していきます。』 と解説してあります。 クラスを継承すると親クラスのプロパティやメソッドが子クラスに継承されるというのは理解できています。私の知っているデータ型(文字列型、整数型、浮動小数点数型、論理型、配列型、オブジェクト型、リソース型、NULL)は下記の2か所だけです。 show()メソッド内の、['%s']と['%s by %s']で文字列が指定されています。 したがってこの項目で説明されている 『Post型の変数を受け取る関数を作って、データ型が継承されることを説明していきます。』 とは、「クラスを継承する際にプロパティやメソッドだけでなく、データ型、ここでは(['%s']と['%s by %s'])も継承されるということが説明されているという解釈でよろしいのでしょうか? 少し混乱しています。もし私の解釈が間違っているようでしたら教えてください。 初学者です。よろしくお願いいたします。 <表示結果>

    • ベストアンサー
    • PHP
  • クラス継承 メンバ引継ぎとprivateについて

    「クラス継承時のメンバ引継ぎの意味」と、 「privateでオーバーライドさせた際の挙動」ついて教えてください。 class Pa{  private $level="10";  public function getLevel(){   return $this->level;  } } class Ch extends Pa{  protected $level="5"; } $ch = new Ch(); echo $ch->getLevel(); このとき、$ch->getLevel();は、 Paクラスのメソッドをchオブジェクトで見に行ってるのでしょうか? それとも、Chクラスに引き継がれたメソッドを見に行っているのでしょうか? また、このときの「$this」「$this->level」は、それぞれ何を意味しているのでしょうか? また、このときの、Chクラスの「$level」は、どういう状態(扱い)になっているのでしょうか? エラーにならないのですが、再定義扱いされないのでしょうか? 新定義扱いされてるってことでしょうか? 「privateメンバを継承した際」、どういう動きをするのか(ルールになっているのか)教えてください。

    • ベストアンサー
    • PHP
  • jQueryのvar jQueryの仕組みについて

    jQuery-1.6.2のソースコードを見ているのですが質問させてください。 25行目の var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); }, そして100行めの jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { の意味が分かりません。 PHP等のclassになれているとJSのクラスは戸惑うことが多いのですが、この例は最たるもので、自分の中のJSでのclassは (1)スーパークラスのプロパティをcall()、apply()で継承 (2)スーパークラスのメソッドをprototypeオブジェクトで継承 (3)インスタンスのデータ型判定に必要なプロパティをconstructorで調整 だったのですが、スーパークラスがどの行のどれなのかも分かりません。 型やメソッド名からこれらがclassを意味しているのは分かるのですが、いったいどの部分がclass定義、継承を行っているのか教えていただけませんでしょうか? なぜこれらがclassになっているのかが理解できません。 分るのは、jQuery.prototype.constructor = jQueryで、それをjQuery.fnに代入((3))している事です。 329行目の、jQuery.fn.init.prototype = jQuery.fn;の右辺がnew {$class}の形であれば(2)のプロトタイプチェーンの形だと分るのですが。 (1)は、init内でメンバ変数を定義したりしているので、classなのかな、という程度しか分っておりません。 jQuery.fnがコンストラクタで、jQueryがインスタンスで、var jQueryは親クラスをinitしたもの?・・・と混乱しております。 質問内容も文章が混乱していて申し訳ないです。

  • オーバーライドの必要性

    まだまだJavaを勉強している途中なのですが、下記のサンプルコードでオーバーライド(メソッドをオーバーロードすることをオーバーライドというのでしょうか…!?)のの必要性がよく分からなくなってしまったので質問させて頂きました。 /* sample.java */ abstract class super_class{  void write(){} } class CLASS1 extends super_class{  void write(){ System.out.println("CLASS1"); } } class CLASS2 extends super_class{  void write(){ System.out.println("CLASS2"); } } class sample{  public static void main(String args[]){   super_class obj = new CLASS2();   obj.write();   obj = new CLASS1();   obj.write();  } } 以上のコードを実行した場合 CLASS2 CLASS1 と表示されるのは多少なりとも勉強して分かったつもりでした…。 しかし、あくまでサンプルであるために特に意味がないことでもオーバーライドの説明をしているのだろうという風に考えてしまったのですが、 結局は、 スーパークラスとサブクラスに同じシグネチャのメソッドがあった場合、各サブクラスのメソッドが実行される と言うことは、スーパークラスのwrite()メソッドは何をしているのでしょうか? 多様性はJavaでも大切なものであるとのことなので質問させて頂きました。 なるべくわかりやすく説明して頂きたいと思います。 どうかお答えをお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう