お世話になります。
Javaのオーバーライドについて質問です。
オーバーライドの利点は、
継承により効率的にスーパークラスの機能を流用しつつ、
必要に応じてサブクラスでその機能を変更することができることだと
Web、書籍等には書いてありますが、これは実行クラスがスーパークラスとサブクラスの機能を順番に呼び出した場合と何が違うのでしょうか。
単純に、実行クラスのコーディングの可読性に優れるという理解でいいのでしょうか。
とんちんかんな質問をしてしまっているかもしれませんが
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答5件
0
ベストアンサー
お邪魔します。
おそらく質問者さんがわからなくなっていらっしゃることは、javaのオブジェクト指向という思想の部分ですね。設計思想というか、コンセプトというか、考え方というか、定石というか。
ポリモーフィズムとカプセル化について学ばれるとよいと思います。
オブジェクト指向においては、「変更に対して開かれており、修正に対しては閉じている」状態を目指すのがよいといわれています。要するに機能の追加や変更は容易でいくらでも付け足すことができ、逆に不具合などによって修正を行う部分は極小(可能な限り1箇所にとどまる)であるべきだ、という考えですね。
そういった思想的背景から、スーパークラスとサブクラスに分けるような機構が考えだされて、処理分割を行うようになりました。(歴史的経緯が正しいかどうかはおいておいて、そうだと思ってみてください。嘘も方便のつもりで書いています。)
よくある感じの説明をすると、人類クラスをスーパーにして、Aさん、Bさんサブクラスを作る場合、人類ができること(メソッド、話すとか歩くとか)の一般的な部分を人類クラスに記述し、AさんBさん固有の動作をAさんBさんクラスにオーバーライドして記述しておけばAさんの動作を変えたい場合にAさんクラスのみを修正すればよく、人類全体に影響が及ばない、ということになります。
また、クラスを使用する側の処理から見ると、より汎用的な型(Abstractやsuper,Interface)に対してプログラミングをしておけば、サブクラスの細かい仕様変更に際して修正を施す必要がなくなります。
同じ処理をいかに1箇所にとどめるか、いかに変更や修正に際して少ない箇所の修正で済むように作るか、という観点で見ると、わかりやすいのではないでしょうか。
投稿2014/12/07 09:58
総合スコア540
0
スーパークラス型の変数にサブクラスのインスタンスを代入し、スーパークラスのメソッド(サブクラスでオーバーライド)を呼び出すと、(スーパークラスではなく)サブクラスのメソッドが実行されます。
スーパークラスやスーパークラスを利用するクラス(サブクラスではなく、java.util.List<?>
など)は、サブクラスの実装に影響されることなく、リリース後の機能強化などが可能です。
つまり、スーパークラスを主体とした利用時にメリットがあるという理解です。
例えばJDBC
は、Javaのリリース当時に現在のMongoDB
などの出現は当然予想していませんが、今現在動いているのはこの恩恵です。
コネクションプーリングなどの機能強化も、まずJDBC
側にメソッドを追加しリリースします。その後サブクラス(DBベンダー)がそのメソッドを実装したものをリリースすれば、利用者側でコネクションプーリングが使えるようになります。
一方、そもそもコネクションプーリング機能がないDBはいつまでも実装しないわけです。
投稿2014/12/06 01:06
総合スコア307
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ご質問の
オーバーライドの利点は、
継承により効率的にスーパークラスの機能を流用しつつ、
必要に応じてサブクラスでその機能を変更することができること
についてはサブクラスのみ生成した前提の説明になります。
オーバライドはスーパークラスのメソッド上書きとなるので、サブクラスにおいてスーパークラスのメソッドは封じられます。ですが、サブクラスのメソッドでsuper識別子を使えばスーパークラスのメソッドを呼び出せるのです。
lang
1class car{ 2 public void accel(){ 3 System.out.println("エンジン駆動"); 4 } 5} 6 7class hibrydCar extends car{ 8 public void accel(){ 9 super.accel(); 10 System.out.println("モーター駆動"); 11 } 12}
オーバライドしたメソッド内でスーパークラスのメソッドを呼びコードを加えることが「効率的にスーパークラスの機能を流用しつつ、必要に応じてサブクラスでその機能を変更することができる」に掛かっていると思います。
スーパークラスとサブクラスを生成してそれぞれでメソッドを呼べば、同じ結果となるケースもありますがそれはまた別の議論になるかと思います。(勘違いでしたら済みません)
投稿2014/12/05 16:38
総合スコア1339
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
これは実行クラスがスーパークラスとサブクラスの機能を順番に呼び出した場合と何が違うのでしょうか。
そもそも,これらを「順番に」呼び出すとは限りません.場合によっては,内部的に全く違う処理を行うことがあります.
例えば,Javaの原始クラスjava.lang.ObjectクラスにはtoString()
メソッドや equals(Object)
メソッドが有ります.
前者はオブジェクトの文字列表現を表し,後者は引数に取ったオブジェクトと比較するメソッドです.
そのまま使うと,toString()
は「クラス名@ハッシュコード」という文字列を返し,
equals(Object)
は引数が自分自身(と同じ参照位置)である場合のみtrue,それ以外はfalseを返します.
そして,これらのメソッドは他のメソッドで使われます.System.out.println(Object)
では引数となったオブジェクトのtoString()
が呼ばれ,その結果を出力します.equals(Object)
はListなどで,対象のオブジェクトと同じものがListに入っているかの判定などに使われます.
この時,元の仕様そのままでは都合が悪いことがあるでしょう.例えばオブジェクトの中身を表示したいのにハッシュコードが表示されたところで意味がありませんし,オブジェクトの中身の比較をしたいのに自分自身としか等しくならないequals(Object)
なんて役に立ちません.
そこで,オーバーライドの出番です.toString()
でオブジェクトの中身を文字列化したものを返したり,
equals(Object)
では中身が完全一致した場合にtrueを返したりという機能を実装したりします.
オーバーライドしたクラスのオブジェクトをSystem.out.println(Object)
に渡せば,オブジェクトの中身を文字として出力できますし,比較もオブジェクトの中身を比較するのでより直感的になります.
こうすることで,スーパークラスであるObjectからの操作記述はそのままに,サブクラスである独自のクラスで独自の操作ができるようになります.
このように,スーパークラスのメソッドを使う場面で,サブクラスでメソッドの操作を変更できるのです.
もしオーバーライドしないのなら,自作クラスで何らかの文字列を返すメソッド(仮にgetString()
とします)を作り,System.out.println(myObject.getString())
と書かなければいけなくなったり,
List内に目的の中身を持つオブジェクトが入っているか調べる際もListのメソッドは使えず,
自分でループ処理を書いてオブジェクトの中身を調べるコードを書かなければならないでしょう.
投稿2015/03/09 15:16
総合スコア20675
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
実行クラスがスーパークラスとサブクラスの機能を順番に呼び出した場合と何が違うのでしょうか。
オーバーライドしないとうまくいかず、上記のような実行クラス側での呼び出しができない例を挙げてみました。
lang
1abstract class DataWriter { // いろいろなデータを出力するベースクラス 2 abstract void writeByte(int byte); 3 void writeInt(int i) { ... } // writeByteを用いて実装されている 4 void writeDouble(double d) { ... } // writeByteを用いて実装されている 5 ... // 他にもwriteByteを用いて実装されている便利メソッドがたくさんある 6} 7 8class StreamDataWriter { // ストリームへデータを出力するクラス 9 OutputStream os; 10 StreamDataWriter(OutputStream os) { this.os = os; } 11 @Override void writeByte(int byte) { os.write(byte); } 12 // 他のメソッドはスーパークラスの実装のままでよいのでこれ以上は何も定義しなくてよい 13} 14 15class BufferDataWriter { // バッファへデータを出力するクラス 16 DataBuffer<Byte> buffer; 17 BufferDataWriter(DataBuffer<Byte> buffer) { this.buffer = buffer; } 18 @Override void writeByte(int byte) { buffer.write(byte); } 19 // 他のメソッドはスーパークラスの実装のままでよいのでこれ以上は何も定義しなくてよい 20}
単なる例のためいまいちなクラスとなっていますが・・・
サブクラスであるStreamDataWriterとBufferDataWriterは出力する先が異なるだけです。お分かりと思いますがスーパークラスはバイトを出力するという機能だけをサブクラスがオーバーライドしてくれれば他のメソッドは自動的にうまく動くように意図して定義されています。
さて、このようなサブクラスに対して「実行クラスがスーパークラスとサブクラスの機能を順番に呼び出す...」というような方法ではwriteByte以外のメソッド呼び出しを記述しようがありません。説明が下手なのでみなさんのような一般性のある説明のしかたができないのですが、こんな例でも参考になるかもと思い記してみました。
いかがでしょうか。
投稿2014/12/11 11:03
総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2014/12/08 01:50
2014/12/13 08:27