• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:継承・実装の関係で悩んでいます。)

継承・実装の関係で悩んでいます

このQ&Aのポイント
  • アクセス制御を考えず、インスタンスかstaticかabstractの違いで継承する方法を検討しています。
  • クラスAからクラスBでオーバーライドしたメソッドは、クラスCでさらにオーバーライドできるのか疑問です。
  • 具体的なクラスの継承関係とインターフェースの実装関係を説明しています。

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

  • ベストアンサー
  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.6

this()とsuper()が同時に使えない件についてです。 this()もsuper()もコンストラクタ内の先頭で記述しなければならないという決まり事もありますが・・・。 また先ほどの回答で挙げたソースコードを元に説明しますね。では下記のソースコードをご覧下さい。 ---------- public class ClassA { protected String a; // インスタンス変数 protected int b; // インスタンス変数 // コンストラクタ1(引数: String, int) public ClassA(String a, int b) { this.a = a; this.b = b; } // コンストラクタ2(引数: String) public ClassA(String a) { this(a, 0); // this()の使用例1 } // コンストラクタ3(引数: int) public ClassA(int b) { this("", b); // this()の使用例2 } } ---------- 上記のソースコードの中で、コンストラクタ2とコンストラクタ3の中ではthis()メソッドを使っているため、super()は呼び出せません。 ではスーパークラスのコンストラクタはどうやって呼び出すのか? コンストラクタ2もコンストラクタ3もthis()メソッドを使って「コンストラクタ1を呼び出し」ているだけです。 ですから、コンストラクタ1にsuper()を追加すればいいのです。 // コンストラクタ1(引数: String, int) public ClassA(String a, int b) { super(); // スーパークラスのコンストラクタを呼び出す this.a = a; this.b = b; } このように記述すれば、コンストラクタ1、コンストラクタ2、コンストラクタ3のいずれもスーパクラスのコンストラクタは呼び出されることになります。 this()メソッドで別のコンストラクタを呼び出している ↓ どこかに実際の処理を行っているコンストラクタがある ↓ そのコンストラクタにsuper()を書く ということです。ちなみに引数なしのsuper()なのか、引数ありのsuper(...)なのかはスーパークラスのどのコンストラクタを呼び出したいかで変わりますが・・・。

pochi1234
質問者

お礼

this(a, 0) のように呼び出した先のコンストラクタで最後にsuper()を呼び出せば良いのですか(super()は書かなくても自動的に呼び出す) super()を呼び出すときは、参考書の例では引数なしバージョンしか書いていませんが、引数ありか、引数なしに気をつけなければいけませんね (引数なしコンストラクタのみthisを書けばいいと思っていましたが、よく考えたら、コンストラクタをオーバーロードして全部で3つあったら、最後だけsuper()のほうがいいですね) とても勉強になりました。 ありがとうございました。

その他の回答 (5)

  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.5

まずthis()メソッドについてです。 下記のソースコードをご覧下さい。恐らくこういう使い方をイメージしていると思いますので・・・。 ---------- public class ClassA { protected String a; // インスタンス変数 protected int b; // インスタンス変数 // コンストラクタ1(引数: String, int) public ClassA(String a, int b) { this.a = a; this.b = b; } // コンストラクタ2(引数: String) public ClassA(String a) { this(a, 0); // this()の使用例1 } // コンストラクタ3(引数: int) public ClassA(int b) { this("", b); // this()の使用例2 } } ---------- 上記のソースコードの中でthis()メソッドを使用している箇所は2つありますが、1つ目のthis()メソッドを例にして説明しますね。 「this()の使用例1」とコメントがあるところで、this(a, 0); と記述していますが、これは引数に(String, int)を渡していますから実際には上記ソースコードのコンストラクタ1を呼び出していることになります。 この場合は変数の初期化だけですから、 public ClassA(String a) { this.a = a; this.b = 0; } と書いても同じことですが、コンストラクタ内での処理が長くなる場合はthis()メソッドを使った方がソースコードがすっきりします。 またthis()メソッドというのは、コンストラクタでの処理はほとんど同じでも引数の種類や数が異なるためコンストラクタが複数作られてしまう場合によく使われます。 例えば、 public ClassA(int a, int b, int c, String d, String e) { // 何らかの処理 } なんてコンストラクタがあったら、使う(newする)側も1つ1つ引数を書かなければならず面倒です。でももし、「特に指定がないなら、b=0, c=0, d=null, e=nullに設定していいよ」という決まり事が出来たら、使う側が毎回 ClassA clsA = new ClassA(1, 0, 0, null, null); と書かなくても済むようにClassA側で新たに public ClassA(int a) { this(a, 0, 0, null, null); } とコンストラクタを作成した方がいいですよね。

pochi1234
質問者

お礼

とてもわかりやすい説明ありがとうございます。 this() = メソッドなんですか? this()は、コンストラクタでの処理はほとんど同じでも引数の種類や数が異なるためコンストラクタが複数作られてしまう場合によく使われるとのことですが、 this() を使うことで、super()が使えなくなってしまいますが、 実際の開発では、this()を多用しても良いのでしょうか? ケースバイケースかもしれませんが。

  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.4

回答#3の補足です。回答#3では分かりやすくするために、 ----- public ClassB() { super(); // ClassAのコンストラクタを呼び出す // その他の処理 } ----- と書きましたが、引数のないスーパークラスのコンストラクタは実際にはコンパイルするときにコンパイラが勝手に追加しちゃいます。ですので、上記のコードはsuper();を明示的に書かなくても結果は一緒なんですけどね・・・。 ClassAの引数のあるコンストラクタで ----- public ClassA(String hehehe) { foo = "hogehoge"; } ----- のように変数等の初期化処理を行っていれば、先の回答#3に書いたようにスーパークラスのコンストラクタを呼び出してやる必要があります。

pochi1234
質問者

補足

super()つけなくても、自動で追加するのは知ってるんです... this()は引数なしコンストラクタにのみ追加するものなのでしょうか?

  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.3

> super()を自動で呼び出すということは、そのクラスのコンストラクタ内で上位クラスのインスタンスを作れる?ということなのでしょうか? super()は継承でコンストラクタをオーバーライドした場合、そのコンストラクタ内の先頭でしか使えませんよ。 例えば、ClassB extends ClassAを考えた場合、 public ClassB() { super(); // ClassAのコンストラクタを呼び出す // その他の処理 } こんな感じです。次に、 public class ClassA { protected String foo; // コンストラクタ public ClassA() { foo = "hogehoge"; // 変数fooの初期化 } } のようにClassAではインスタンス変数をコンストラクタの中で初期化している場合を考えてみましょう。 ClassB extends ClassAで継承したら、ClassBの中で何も宣言しなくても変数fooが使えるというところは理解できましたか? 例えば、ClassBの中で public void methodB() { System.out.println(foo); } のように、ClassBの中で宣言していない変数fooが使えます。これはClassAから変数とメソッドを引き継いでいるからです。 さて話を戻して、変数fooは「ClassAのコンストラクタの中」で初期化されています。ということはClassBの中で、初期化された変数fooを使用したければClassBの中でClassAのコンストラクタを呼ばないといけませんよね? そういった場合に、 public ClassB() { super(); // ClassAのコンストラクタを呼び出す // その他の処理 } とsuper()を使います。

pochi1234
質問者

お礼

super()については少し理解できました、this()の場合ですが、 例えとして、newで何も設定しなかったときに、this("NO NAME", 0); みたいな使い方をして、 次のコンストラクタに渡すと思うのですが。 やはりコンストラクタが3つ以上ある場合が多いと思います。 そうすると次のコンストラクタでもthis()を使ってしまうと、super()を呼び出せなくなってしまうので、そこが疑問です。 もしかして、引数2つあったとしたら、3つ目のコンストラクタに飛びますね(コンストラクタはオーバーロードしてるし) つまりthis()は、クラスの最初にある、引数なしのコンストラクタにのみ使ったほうがいいのでしょうか?

  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.2

サブクラスのサブクラスなんてJavaのクラスではいくらでも出てますよ。 JavaのAPIリファレンスを参照することができるのであれば、java.util.LinkedHashSetクラスをご覧になって下さい。 様々なクラスを継承した上で多数のインタフェースを実装してますよ。 > クラスAを変更したときに、クラスCにどう影響がでるのか、 クラスA内で実装しているメソッドを変更しても、それをオーバーライドしているクラスCのメソッドには何も影響は出ませんよ。 ただし、オーバーライドする中で public void methodA() { super.methodA(); … } のようにスーパークラスのメソッドを呼び出している場合は別ですが・・・。 継承やオーバーライドについてはあまり難しく捉えずに理解するようにして下さい。 それから、疑問に感じたら一度ご自分でコードを書いて動作を確認してみるのも1つの手ですよ。

pochi1234
質問者

お礼

サンプルソースを作ってみたところオーバーライドの意味を理解できました。 private フィールドにすることで、インスタンスが変な動作をすることもありませんですし、必要なメソッドだけオーバーライドして、すでに作らているものは再利用できるということを理解しました。 ただコンストラクタのsuper()について、そのメリットが理解できなくて困っています。 this()を使えば、super()は呼び出されませんが。 super()を自動で呼び出すということは、そのクラスのコンストラクタ内で上位クラスのインスタンスを作れる?ということなのでしょうか? 意味不明な質問ですいません。

  • x_jouet_x
  • ベストアンサー率68% (162/236)
回答No.1

まず1点、「継承」というのはスーパークラスに実装された変数やメソッドを引き継ぐということです(privateは除きますが)。 例えば特に明示しない場合、全てのクラスのスーパークラスはObjectクラスになっているので、Objectクラスに実装されたfinalize()メソッドやgetClass()メソッドはサブクラスの中で実装していなくても使用できる仕組みになっています。 オーバーライドというのはその名の通り、スーパークラスから引き継いだメソッドをサブクラスの中で上書き(処理を変更)するということです。 例えば、上記に挙げたgetClass()メソッドはサブクラスの中でオーバーライドされていればそれが呼び出され、オーバーライドされていなければObjectクラスのgetClass()メソッドが呼び出されるだけです。 それを踏まえて、 >クラスAからクラスBでオーバーライドしたメソッドは、 >クラスCでさらにオーバーライドできるのでしょうか? もちろんできます。 クラスCでオーバーライドしていない場合でも、クラスC内でそのメソッドを呼び出すことも可能です。この場合、クラスBで実装した処理が行われます。 >クラスCが クラスBのクラスAからオーバーライドしたメソッド >をクラスBのメソッドとして見たときに、オーバーライドすることは可能なのでしょうか? この質問が今ひとつ分かりません(すみません)。

pochi1234
質問者

お礼

オーバーライドできるんですか、 クラスが2階層だと理解できるのですが、 3階層になると急に理解できなくなってしまいます。 クラスAを変更したときに、クラスCにどう影響がでるのか、 メソッドとコンストラクタについて、私はまだよく理解していないみたいです。汗

関連するQ&A