interfaceの利点は
interfaceの実装先に特定のメソッドのOverrideを義務付けるとともに
同名関数の衝突回避をしながら擬似的な多重継承を可能にするようなものだと考えていました。
ところがJAVA SE 8からinterface内にdefault実装というものができてしまいまったせいで
私の中では整理がつかずabstract修飾子をつけたclassとの差が分からなくなってしまいました。
そもそものinterfaceの捉え方が間違っていたということが発覚し非常にショックです。
せっかくの申年ですし
interfaceとabstract classの違いを猿にでも分かるように説明いただきたいです。
(一般化した言い方ではなく具体例を出していただけると非常に助かります。)
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
java
1 2package com.test.swing.util; 3 4public class C implements A,B { 5 6 public void test() { 7 System.out.println("C test called."); 8 } 9 public static void main(String...args) { 10 11 C c = new C(); 12 13 c.test(); 14 15 A a = new C(); 16 17 a.test(); 18 19 B b = new C(); 20 b.test(); 21 } 22} 23 24package com.test.swing.util; 25 26public interface B { 27 default void test() { 28 System.out.println("C test() call."); 29 } 30 31} 32 33package com.test.swing.util; 34 35public interface A { 36 37 default void test() { 38 System.out.println("C test() call."); 39 } 40} 41
結果:
C test called.
C test called.
C test called.
default メソッドめちゃくちゃ便利じゃないですか。何を迷うとこあるんです?
継承先で集約できるんですよ。多重継承の逆版みたいな感じですね。
C.test を実装しない場合、構文エラーになりました。
まぁ、"default" な実装なので、名前は確かに衝突する可能性は高くなりますが、
2つの異なる振る舞いを1つに集約できるという点では、自分的には OK です。
回答になっていませんが。
投稿2016/01/14 15:11
総合スコア1693
0
abstract classはクラスなので、継承しないと使えません。
他のクラスを継承したクラスに更にこのクラスの機能を加えて…という芸当はできません。
しかし、クラスフィールドを持つことができ、独立した情報を持つことができます。
ほか、コンストラクタなどを定義することもできます。
一方interfaceは継承関係に縛られずに実装できます。
一方、定数でないフィールドを宣言できないので、インタフェースが情報を持つということができません。
あくまでインタフェースは操作の入り口なので、「操作方法」を提供しているに過ぎず、
デフォルト実装は「既定の操作」を設定しているだけです。
投稿2016/01/14 14:22
総合スコア20651
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/01/14 15:02
0
Java だけでなく、最近のクラスベースのオブジェクト指向に共通しそうな話題ですね。
質問者の開発言語経験など背景がちょっと解りませんが、文面を見ると実装だけの考えで捉えすぎているように見受けられます。もっと設計に比重を置いた捉え方ができるようになると、たぶん、その質問/疑問は解消するのではないでしょうか?
オブジェクト指向でのクラス継承を親子の縦方向の関係とすると、インターフェイス実装は共通性のある横方向の関係をイメージすると良いかもしれません。クラス継承を行う場合は必ず親は1つ。インターフェイス実装を行う場合は複数可能で、Java の場合はこれらを単体でも、組み合わても使える言語になっています。インターフェイスにデフォルト実装が加わってもこの関係は変わりませんし、無理してデフォルト実装を使う必要はありません。(効果的に使えるならば使うほうが明らかに便利だと思いますが)
※ ただし、同じメソッド名のデフォルト実装を複数使う場合は多重継承における菱形継承問題と同様の問題が発生するため、ipadcaron さんが回答されているコードの通り、明示的に override しなければコンパイルエラーとなるはずです
設計を度外視した実装だけで考えれば、abstract class を使っても、それと同じような default 実装の interface でも、同じ結果を得るための処理は実現できるでしょう。ただし、それぞれのクラス構成や結果を得るための思想は全く異なります。クラスやらの要素の在り方が設計上の違いとして表れているはずです。
クラス継承とインターフェイス実装の参考になりそうなもので思いつくのは、例えば、デザインパターンでの Template Method と Strategy 辺りが(ちょっと難しいかもしれませんが)それぞれ参考になるのではないでしょうか?
インターフェイスの凄さは、大量の異なるクラスを横断的に扱うような状況など、それなりの規模にならないとなかなか実感しないかもしれませんが、効果的に使えるようになると保守性も上がりますし、とっても便利ですよ。まぁ、あとは集約/合成(コンポジション)が解るともっと面白くなると思います。
投稿2016/01/14 15:59
総合スコア433
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/01/14 16:38
2016/01/15 03:55
0
default実装を衝突の可能性が生まれるのにいいのか?
なら多重継承を禁止する意味がないじゃないか!
というパニック状態のままabstractが云々...と沼にはまってしまいました。
改めて考えると自分の中で
多重継承の利点がコードの再利用のみに偏っていました。
JAVAでは何故、多重継承が禁止されているのかと考えた時に
「多重継承の存在によってコードの再利用が乱用され
本来のオブジェクト指向から離れて行ってしまう可能性があるから」なのでは?
と自分の中で合点がいきました。
そして衝突が起きる場合は構文エラーを吐いてくれるんですね!!
ipadcaron様ありがとうございます。
「なんだこれ意味ねぇじゃん。使わねーよ。」とか思って試そうともしなかった少し前の自分を
ぶん殴りたいです。
検証不足のまま質問してお二人の貴重な時間を割いてしまい申し訳ありませんでした。
反省します。
ありがとうございました。
投稿2016/01/14 15:56
総合スコア26
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/01/14 15:22
2016/01/14 16:57