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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

Q&A

解決済

4回答

979閲覧

継承の使い方について

fumimimi

総合スコア16

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

継承

継承(インヘリタンス)はオブジェクト指向プログラミングに存在するシステムです。継承はオブジェクトが各自定義する必要をなくし、継承元のオブジェクトで定義されている内容を引き継ぎます。

0グッド

1クリップ

投稿2019/08/31 13:40

Java初心者です。

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

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

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

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

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

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

よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

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

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

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

java

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

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

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

java

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

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

投稿2019/09/01 05:52

ozwk

総合スコア13512

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fumimimi

2019/09/02 12:16

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

0

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

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

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

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

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

投稿2019/08/31 17:47

gentaro

総合スコア8949

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

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

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

java

1class Animal { 2 public String bark() { 3 return "動物が鳴きます"; 4 } 5 6 public String walk() { 7 return "動物が歩きます。"; 8 } 9}

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

java

1class Dog extends Animal { 2 @Override 3 public String bark() { 4 return "犬がワンワンと鳴きます"; 5 } 6 7 @Override 8 public String walk() { 9 return "犬がトコトコ歩きます。"; 10 } 11}

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


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

java

1class A { 2 public int value = 5; 3} 4class B extends A { 5 public String value = "Hoge Hoge"; 6}

java

1class Test1 { 2 void method() { 3 B b = new B(); 4 System.out.println(b.value.endsWith("ge")); 5 } 6}

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

java

1class Test2 { 2 void method() { 3 A a = new B(); 4 System.out.println(a.value.endsWith("ge")); 5 } 6}

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

以上余談でした。

投稿2019/08/31 22:16

編集2019/08/31 23:27
frodo821

総合スコア322

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/08/31 22:23

> 逆に言うと、サブクラスの動作はすべてスーパークラスで想定された動作になっているはずです。 そんなことはないと思います。
Zuishin

2019/08/31 22:27

> GUIのButtonくらすは黄色くないかもしれません。仮にこれを黄色くするため、Buttonを継承してYellowButtonというクラスを作ったとすると、YellowButtonクラスは「黄色」というより特化した特徴を付け加えるために作ったButtonのサブクラスと考えるべきです。 これもかなり誤解を招く表現です。通常、ボタンの色を変えるのに継承は必要ありません。間違ってはいないかもしれませんが、初心者への説明の例としては混乱を招き、不適切です。
frodo821

2019/08/31 22:34 編集

少し言葉足らずでした。 「サブクラスの動作はスーパークラスで定義されたすべての関数、プロパティ、変数においてスーパークラスの挙動と等しいはずです。ただしここで言う挙動とは、引数の数、型及び戻り値の型、uncheckedを除く例外の種類を指します。」というのが一番丁寧な説明ですね。
Zuishin

2019/08/31 22:29

その説明も間違っています。
frodo821

2019/08/31 22:33

いや、スーパークラスで定義されているものならサブクラスでOverrideしてもシグネチャは共通でしょう。
Zuishin

2019/08/31 22:35

まずシグネチャは動作でも挙動でもありませんし、オーバーロードや隠蔽というものもあります。
frodo821

2019/08/31 22:43

オーバーロードは内部的に呼び出す関数をシグネチャによってディスパッチしているだけですし、それぞれの関数をサブクラスでOverride可能です。隠蔽の場合でもシグネチャは一致しているので呼び出し側は全く同じようにつかえますよね。 呼び出し側から見た動作(何を渡したら何が返ってくるのかということ、この表現自体が誤解を招くものかもしれませんが。)は一致しています。
Zuishin

2019/08/31 22:48

あなたの言っているのは「メソッドをオーバーライドするためにはシグネチャを一致させる必要がある」ということですが、その表現方法が間違っているために、そうは読みとれません。また、この文脈で何のためにそれを言うのか理解不能です。
Zuishin

2019/08/31 22:52 編集

隠蔽とオーバーライドが同じように使えるというに至っては完全に説明を放棄して言い訳に終始しているようにすら見えます。 同じようには使えません。
frodo821

2019/08/31 23:00

フィールドの場合、隠蔽は型が異なる可能性があります。そのうえ、隠蔽はapparent typeの方がアクセスする際に影響します。そういう意味では確かに同じように使えません。 オーバーライドの説明ですが、「スーパークラスとサブクラスで呼び出し元がやることは同じ」ということが言いたかったので表現を改めます。
Zuishin

2019/08/31 23:25

ありがとうございました。
fumimimi

2019/09/01 05:07

frodo821さん 初心者で、的が得られていない質問にも関わらずご丁寧にご回答いただき誠にありがとうございます。 例もとてもわかりやすかったです。 ひとつ加えて質問させていただきたいのですが、 @Override public String bark() { return "犬がワンワンと鳴きます"; 子クラスのDogクラスに泣くというメゾットを書くのであれば、そもそもAnimalクラスの継承はせず、Dogクラスに必要なメソッドを書けばいいのではないかと感じてしまいます。 親切に教えてくださっているにもら関わらず理解が弱く大変申し訳ございません。 Zuishinさん 色々アドバイスいただき、初心者ということにもお気遣いいただきありがとうござます。 シグネチャなど経験したことない用語があり、何も返せず申し訳ないです。 勉強を深めていき、理解できるよう学びます。
frodo821

2019/09/01 08:24

同様のクラスが犬しかない、これ以上増えない場合は確かにDogクラスのみ用意すればいいでしょう。ですが、同じメソッドやフィールドなどを持つCatクラスやCowクラス等を追加していった場合、個々のクラスを別々に作っていけば、呼び出し側と個々のクラスとの間での結合が強くなってしまい、追加する度に条件分岐やオーバーロード関数が増えていってしまいます。 そこで、共通の部分をAnimalというスーパークラスとして実装することで、呼び出し側はAnimalのサブクラスでさえあれば、DogだろうがCatだろうがCowだろうが、全く同じAnimalとして扱えます。つまり、サブクラスのインスタンスはスーパークラスのインスタンスとしても扱えるということが一番の意味なのです。 先の例で言えば、DogクラスのインスタンスはAnimal型に暗黙にキャストできます(この操作をアップキャストといいます)し、Animal型の変数に代入できます。当然、Animal型のオブジェクト対して可能な操作は成功するか否かは置いておくとしてもDogクラスでも可能です。一方、Animalクラスをスーパークラスに持たないHogeクラスを作ったとして、当然にこのようなことはできません。 フィールドを持たない場合はinterfaceというものを使ってもほぼ同じことが実現できますが、こちらはその名の通りメソッドの存在とシグネチャの共通性を保証することで、同じインタフェースを実装しているクラスであれば同じように外部からアクセスできるようにするというものになります。
fumimimi

2019/09/01 13:36

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

2019/09/01 13:38

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

0

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

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

投稿2019/08/31 13:47

jimbe

総合スコア12545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問