質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.11%

継承の使い方について

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 249

fumimimi

score 6

Java初心者です。

継承は親クラスのもつ属性や振る舞いを受け継ぐとのことですが、
この意味を理解しているつもりでいました。

しかし、勉強を前の章に戻ってみたところ、同じパッケージ内のクラスであれば、セッター、ゲッターを使って、メソッドや変数を取りに行くことができます。

継承もsuperをつかって、親クラスのメソッドを使うので、意味が一緒な気がしてしまい、むしろ継承は親クラスはひとつしかもてないのであれば、同じクラスのセッター、ゲッターでとりにいけばよいのではないかと考えてしまいました。

インスタンスも他のクラスで作っていたので、継承しなくても他のクラスで準備ができているため、ますますわからなくなってしまいました。

意味をしっかりと理解できておらず、このような質問となっています。

正しい理解をしたいので、ご教示いただけたら嬉しいです。

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+3

基底クラスの変数に派生クラスのインスタンスを代入できる(メソッドの引数含む)ことが継承を使う一番の動機です。
そういう利用方法をしないなら継承を使う意味はないと思ってください。
振る舞いを受け継ぐのは、「継承して何もしなければそうなる」だけであって目的ではないです。

で、代入できたり引数に入れたりできると何がうれしいかというと、使う側のコードが簡略化されます。

大枠での目的が似ているクラス(例えば、ファイルに書き出すけど形式が違うとか)C,Dがあって、
それぞれf()というメソッドがあったとしましょう。
別のクラスでC.f(),D.f()の結果を使って何かする、
ただし違いはCをつかうかDをつかうかだけのメソッドがあったとすると、こんな感じで書くと思います。

void someMethod_C(C c){ /* c.f()を使ってなにかする */}
void someMethod_D(D d){ /* d.f()を使ってなにかする */}

C,Dに続いてさらにクラスを追加すると、追加した分だけsomeMethod_Xが増えることになります。

ここで、C,DがクラスBを継承していたとすると、

void someMethod(B b){ /* b.f()を使ってなにかする */}

の1つにまとめることができて、似たようなクラスが追加されたとしてもここに変更はありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/02 21:16

    とても分かりやすかったです。ありがとうございました。

    キャンセル

+2

継承の使い方について一番わかりやすいのはGUIの部品だと思います。

「ボタン」と「チェックボックス」はそれぞれ別のクラスですが、共通点も数多くあります。(クリックができる、ラベル(表示用のテキスト)、背景色を持っている、等)

その共通点を例えば「UIコントロール」などに全て実装しておいて、「ボタン」や「チェックボックス」は「UIコントロール」を継承すれば、後はそれぞれ独自の処理だけを実装できます。(差分プログラミング)

ここで、「全てのUIコントロールの背景色を黄色にしたい」という処理を行いたい場合、「ボタン」や「チェックボックス」といった特定の型でなく、「画面上にある全てのUIコントロール」に対して「背景色を黄色にする」処理を書くことで、全部まとめて操作することができます。

継承を使っておらず、「ボタン」や「チェックボックス」が全て独自の型で合った場合は、「画面上にボタンがあれば、黄色にする」「チェックボックスがあれば、黄色にする」などの処理を個別に書く引く必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

クラスの継承に関しては、非常に重要な考え方が存在します。その考え方にはリスコフの置換原則という大層な名前がついていますが、実際そんなに難しいものでもないです。簡単に説明すると、「車は走るものだ」と決めた(決まっている)なら、車の派生であるスポーツカーも、バスも走らなくてはならないということです。

今、Animalというクラスがあったとしましょう。Animalは鳴かなくてはいけません。そして歩く必要もありそうです。この仕様を実装してみます。

class Animal {
    public String bark() {
        return "動物が鳴きます";
    }

    public String walk() {
        return "動物が歩きます。";
    }
}

このクラスは「動物とはこういうものである」という仕様を決めてあるだけにすぎません。ベースクラスとは、得てしてこういうものです。仕様と最低限の実装のみ。このクラスは、犬の動作を含んではいますが、犬そのものは表せません。そこで、これを継承したDogクラスを作ります。

class Dog extends Animal {
    @Override
    public String bark() {
        return "犬がワンワンと鳴きます";
    }

    @Override
    public String walk() {
        return "犬がトコトコ歩きます。";
    }
}

さて、DogクラスはAnimalクラスより正確に犬という存在を表しています。いいかえると、DogクラスはAnimalクラスより犬に特化したクラスとなっています。しかし、あるクラスを継承しているのならば、そのクラスを実際に使う側は何も考えずにそのあるクラスと全く同じ使い方ができます。この例で言うならば、「動物全体からその派生である犬に限定したとしても、動物が鳴くし歩くなら、犬も鳴くし歩く」のです。これが継承の一番重要なポイントです。これは要するに、スーパークラスの場所を任意のサブクラスで置き換えたとしても正常に動くはずであるということになります。


追記
javaには隠蔽という仕様があるため、必ずしもそうとは言えない場面も存在します。たとえば、次のAとB二つのクラスに対して、Test1は正しく実行できます。

class A {
    public int value = 5;
}
class B extends A {
    public String value = "Hoge Hoge";
}
class Test1 {
    void method() {
        B b = new B();
        System.out.println(b.value.endsWith("ge"));
    }
}

一方、Test2はコンパイルできません。

class Test2 {
    void method() {
        A a = new B();
        System.out.println(a.value.endsWith("ge"));
    }
}


というのも、隠蔽の場合は実際の型(変数に格納されたオブジェクトの型)ではなく、見た目の型(変数の型)がアクセスする先に影響するからです。ここがオーバーライドとは大きく違う点です。

以上余談でした。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/01 17:24

    同様のクラスが犬しかない、これ以上増えない場合は確かにDogクラスのみ用意すればいいでしょう。ですが、同じメソッドやフィールドなどを持つCatクラスやCowクラス等を追加していった場合、個々のクラスを別々に作っていけば、呼び出し側と個々のクラスとの間での結合が強くなってしまい、追加する度に条件分岐やオーバーロード関数が増えていってしまいます。

    そこで、共通の部分をAnimalというスーパークラスとして実装することで、呼び出し側はAnimalのサブクラスでさえあれば、DogだろうがCatだろうがCowだろうが、全く同じAnimalとして扱えます。つまり、サブクラスのインスタンスはスーパークラスのインスタンスとしても扱えるということが一番の意味なのです。

    先の例で言えば、DogクラスのインスタンスはAnimal型に暗黙にキャストできます(この操作をアップキャストといいます)し、Animal型の変数に代入できます。当然、Animal型のオブジェクト対して可能な操作は成功するか否かは置いておくとしてもDogクラスでも可能です。一方、Animalクラスをスーパークラスに持たないHogeクラスを作ったとして、当然にこのようなことはできません。

    フィールドを持たない場合はinterfaceというものを使ってもほぼ同じことが実現できますが、こちらはその名の通りメソッドの存在とシグネチャの共通性を保証することで、同じインタフェースを実装しているクラスであれば同じように外部からアクセスできるようにするというものになります。

    キャンセル

  • 2019/09/01 22:36

    frodo821さん
    ありがとうございます。
    重ねて質問してしまい、申し訳ないです。お手すきでご回答いただけると嬉しいです。
    親クラスで書いたメソッドは子クラスでは必ず全て使う必要はありますか。
    そのようなルールはないでしょうか。
    親クラスは混乱を防ぐため、最小限の定義をすると記載がありました。

    キャンセル

  • 2019/09/01 22:38

    必ずしもすべて使う必要はないです。

    キャンセル

0

継承は親クラスのもつ属性や振る舞いを受け継ぐ

だけが継承する意味ではありません.
子クラスは親クラスとして使えるということが継承する本来の意味かと思います.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる