下記の質問と重複するかもしれませんが・・・・
オブジェクト指向を勉強している者です。説明が下手ですいませんが、
↑**これのみを定義(記述)**しておくことで、
0. 「基準(ルール)を定める」
1. 「ルール(規格)を強制できる(ルール違反できない)」
上記のメリットがありますが、そこで疑問があるのですが、
「インターフェース」を使えることによる、その**「メリット」と「デメリット」**とは何なんでしょうか?
つまり、インターフェース(ルールを強制させる)を使うことで、
「何が嬉しいのか?」
「何が便利になるのか?」
ということです。
そもそも**「ルールを強制させる為にインターフェース使うぞ!」とは思えないはず**です。
**「インターフェース」における本質(の目的)**は何なんでしょうか?
(できれば)日常的に例えたもののほうがわかりやすいです。
さらに・・・
【Java入門】interface(インターフェース)の使い方 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
↑このサイトに**「インターフェース」を使うメリット**が載ってあるんですが、そこには
でも、具体的に書かないメリットがあるんです。
それは、実際に処理を実行する直前に処理内容を決められるんです。
ということは、処理を後で変えることもできるんです。
後になって、処理を変えたい場合はありませんか?
そんな時に該当する場所をわざわざ探しに行って変える必要がないんです。
これってとても便利ですよね。
(・・・省略)
でもinterfaceを使えば、MultiplyクラスのようにMainクラスと同じファイル内に処理の変更を記述することができます。
探して書き換える手間が省けるのがメリットなのです。
処理が複雑になり記述量が多くなると、多数のファイルに分けて記述するという機会が増えます。
そんな場合はinterfaceでメソッドの型だけ宣言しておいて処理は別で記述する方が、後々の変更などが予想される場合には便利になってくるのです。
↑このように書かれておりますが、
「ルールを強制させる」のと「手間が省ける」
↑どういう関係があるのでしょうか?
さらに
上記のサイトには「インターフェースにおけるデメリット」が載っており、そこには
中身が空っぽというデメリットは、「委譲」で回避できます。
委譲とは、実装済みのクラスに処理を委ねてしまう(単なるクラス呼出し)です。
と書かれていますが、インターフェースにおけるデメリットというのはこういうことなんでしょうか?(日常的な例えのほうがわかりやすいです。)
長文になって失礼しまいますが、回答のほうお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
こんにちは。
そもそも「ルールを強制させる為にインターフェース使うぞ!」とは思えないはずです。
そんなことは全くありません。ルールを強制させるためにインターフェースを使います。
これにより、間違ったルールでクラス・メソッドを呼び出そうとした時、処理系がエラーを報告するので間違いに早期に気がつくことができます。その御蔭で、そのような間違いを犯していないかのテストを省略でき、プログラムの信頼性を保ちつつ納期を短縮できます。
また、同じような機能を持つクラス毎に使い方が一々異なっていると面倒極まりないです。それらのクラスが同じインタフェースを継承していることが分かれば、使い方も同じであることが分かりますから、使う側にとって非常に楽になります。
(できれば)日常的に例えたもののほうがわかりやすいです。
ちょっと前の質問に日常的に例えて回答した記憶があります。
自動車のアクセルとブレーキの操作方法が、現在のほぼ全ての自動車で統一されていることは自動車を運転する人にとって非常にありがたいです。
もしも左がアクセル/右がブレーキのような自動車が合った場合、左がブレーキ/右がアクセルの自動車に習熟している人は、その自動車へ乗り換える時、再習熟訓練をするべきではないでしょうか? そしてちゃんと操作できることを確認した上で運転許可を与えるべきと思います。そんな世界はナンセンスでしょう。
恐らく自動車のアクセルとフレーキの操作方法(インターフェース)は、法律で強制されているのではないかと思います。その御蔭で、我々は自動車の運転方法を1種類学ぶだけでほとんどの普通自動車を運転できます。
プログラミングの世界のインターフェースも同様です。1種類のインターフェースの使い方を学ぶだけで、そのインターフェースを継承している全てのクラスを使えるようになるのですから、本当に楽になりますよ。
更に、多くの自動車と異なり、明らかな誤操作(誤呼び出し)は事前に(コンパイル時に)エラーを出してくれるのですから、至れり尽くせりです。
中身が空っぽというデメリット
これは、「インターフェース」という仕組みを持つ言語における通常のクラスを継承する場合とインターフェースを継承する場合の差の話です。mr0237さんの質問を見る限り、クラスの継承とインターフェースの継承を比較されているようには見えませんので、このデメリットは現在の質問の主旨のデメリットには該当しないと思います。
インターフェースにより使い方を統一し、それを強制することのデメリットは、それが必要な場合にはあまりないように思います。
【追記】
ところで、一般的なインタフェースは「①定数 ②メソッド名」という形式の定義ではありません。
多くの場合「メソッド名とシグニチャ」を定義します。シグニチャは当該メソッドの「戻り値の型、引数の型の並び」を定義する言語が多いです。int foo(int, short, string);
などですね。
投稿2018/06/23 10:50
編集2018/06/23 10:58総合スコア23274
0
- インターフェースを実装したクラスは、インターフェースが持つメソッド確実に持っている
- インターフェースを実装したクラスはインターフェース型の変数に入れられる
インターフェースを実装する側にメリットが有るのではなく、
インターフェースをを受け取ってなにかする側にメリットがあります。
というわけで、インターフェースを実装する側を眺めててもメリットは全然わかりませんし、
使う側も、インターフェース型の変数なり引数を使わなければただいたずらにコードが増えただけになります。
教科書的な例ですが、画面に文字を出すScreenWriter
クラスと、
それを使ってHelloWorldを出力するGreeter
クラスがあったとします。
public class Greeter{ public void sayHello(ScreenWriter w){ w.write("HelloWorld"); } }
ここで、ファイルに出力できるように機能を追加したいとします。
ファイルに文字を書くFileWriter
クラスを作り、Greeter
にもう一つメソッドを生やします。
public class Greeter{ public void sayHello(ScreenWriter w){ w.write("HelloWorld"); } public void sayHello(FileWriter w){ w.write("HelloWorld"); } }
(どちらに出力するかは、Greeterを使う側が決定するものとします。)
この方法だと出力先の候補が増えるたびにメソッドが増えます。
あからさまに無駄ですね。
そもそもGreeter
クラスはただ挨拶がしたいだけで、
出力先が何かを細かく知っていると面倒が増えるだけです。
では何でも渡せるように、引数の型をObject
にするとどうなるでしょうか?
Objectは定義上、write()メソッドを持っていないので、当然コンパイルエラーを起こします。
そこでインターフェースを使うとこうなります。
ScreenWriter
とFileWriter
が
write()
メソッドを持つIWritable
インターフェースを実装していたら、
public class Greeter{ public void sayHello(IWritable w){ w.write("HelloWorld"); } }
IWritable
はwrite()
メソッドを持っているのでGreeter
側ではこれで問題ありません。
仮に実装クラスでwrite()
をうっかり実装忘れしていたらコンパイルエラーにしてくれます。
(これを指して、「メソッドを持つように強制されている」)
そもそも「ルールを強制させる為にインターフェース使うぞ!」とは思えないはずです。
思うんです。
プログラマーが意図しないミスをしたときに、実行時に気づくのではなく、
コンパイルエラー(ここで言うルール)になってくれたほうが
自動でミスを見つけてくれることになるので圧倒的に楽なんです。
「~~Writerっていう名前のクラスなんだからWrite()を持っている」という人間が勝手に決めたことを
コンパイルエラーという形で厳格に守れるようになります。
投稿2018/06/23 10:57
編集2018/06/23 11:09総合スコア13553
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
カセットコンロとそのボンベの規格が、1998年の阪神淡路大震災をきっかけに統一されたことはご存知でしょうか?
それまではメーカーごとに独自の規格を持っていたため、ボンベの貸し借りなどができず、不便な状況になっていたのです。
規格が統一されたことにより、(完全ではありませんが)コンロと異なるメーカーのボンベでも使うことが可能となり、非常に使いやすくなったのです。
これに限らず、DVDやUSBなどはルールを統一しているからこそ、広く利用されるようになったのです。
投稿2018/06/27 16:54
総合スコア20673
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
いろいろ答えを書かれていますが、オブジェクト指向に基づいた視点から。Java におけるインターフェースがなぜ作られたのか、という点からアプローチしてみます。
そもそも Java がインターフェースを採用したのは、それまでのオブジェクト指向プログラミングの主力であった C++ における多重継承の問題を回避するためです。
では多重継承とは何か。
通常、オブジェクト指向におけるクラスの親子関係は、1:n になります。あるクラスにとって、親は一つなのです。ところがオブジェクト指向プログラミングを実践するようになって、この 1:n では処理しきれない親子関係が発生することが分かってきました。
※ペット - 犬と、ペット - 猫、ペット - 金魚 のような関係だとして、犬と猫は「鳴く」のですが金魚は鳴きません。なので、共通の親に当たるペットに「鳴く」を付け加えられないのですが、そうすると犬と猫の「鳴く」は別のメソッドになってしまい、多態性が損なわれます
C++ では親クラスを複数にすることで回避しましたが、親が複数いるという状態は別の弊害を引き起こしてしまい、C++ のオブジェクト指向を難解なものにしてしまうことになりました。
上記の例でいえば、もう一つ、ペット - 鳴くペット というクラスを定義し、ここから鳴くペットと犬 - 鳴く犬、鳴くペットと猫 -鳴く猫、のような継承関係(菱形継承)で実装するなどです。
もっともこの程度なら、ペット - 鳴くペットと、ペット - 鳴かないペット として、さらに鳴くペットから犬と猫を、鳴かないペットから金魚を派生させてもうまくはいくのですが、クラス樹形図全体が変わってしまうため、思わぬところに影響が出てしまう可能性があります。これは定義するクラスの数が増えるごとに、また複雑さが増すごとに幾何級数的に増大していくので、破たんしやすいのです。
この反省に基づき考えられたのがインターフェースです。インターフェースでは「鳴く」という動作(メッセージ)のみを定義します。なので、あるクラスに「鳴く」インターフェースを付与する、という形で拡張できるようになっています。
インターフェースは動作(メッセージ)を定義しますから、そのクラスの実装ではかならずその動作を実装しなければなりません(仮に「何もしない」動作だとしても、そういう実装をしなくてはならない)。
※インターフェースの定義そのものは「抽象型」であって、実装をもちません。インターフェースを追加したクラスで、実装をすることになります。
オブジェクト指向プログラミングの歴史を追いかけると、疑問が解消しやすいかと思います。
投稿2018/06/27 00:57
総合スコア13705
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
例えば
◁◁
□
▷
▷▷
というボタンが何かの機器についていたとしましょう。
▷
ボタンは何かを時系列にそって順送りに動かす機能だろう、□
ボタンはそれを停止する機能だろう、と想像がつくんじゃないでしょうか?
それがインタフェースの持つ能力です。
作る側から見てみると、それがカセットテープだろうと、CDだろうと、音楽プレイヤーだろうと、ソフトウェアだろうと、上記のような機能をもっている「なにか」であれば、このインターフェースを共通して搭載できるといことと、このインタフェースを搭載しさえすればその使い方が伝わることがインタフェースの持つ能力です。
プログラミングでインタフェースの利便性を想像するにはGUIのことを考えるのが一番いいと思うのですが、Javaはその辺に手を出すと途端に難しいので、架空のプラットフォームを考えましょう。
まず、複数行の文字列を書けるテキストエディットを考えます。
あるテキストエディットからあるテキストエディットに内容をコピーする手続きが欲しくなりました。
何行のデータを持っているかを調べるメソッドlen
と、何行目を指定して文字列を取り出せるメソッドget
と、文字列を末尾に追加するメソッドadd
と、内容を空にするメソッドclear
があるとしましょう。
procedure copyLinesTextEdit(a: TextEdit, b: TextEdit) i: int begin b.clear() for i = 1 to a.length b.add(a.get(i) next end
みたいな擬似コードになりますね。
さて、GUIにまた別の要素、リストボックスがあるかもしれません。同じメソッドのリストボックス版がほしくなりました。
ではここでインタフェースが存在しない言語をまず想像してください。どうしますか??
procedure copyLinesListBox(a: ListBox, b: ListBox) i: int begin b.clear() for i = 1 to a.length b.add(a.get(i) next end
という別の手続きを定義する以外にないんです(なにか小難しい機構をひねり出さない限り)。
GUIにはコンボボックスもあるかもしれません。複数行チェックボックスを簡単に書けるコンポーネントがあったりするかもしれません。全部定義しますか?
あるとき不意に、テキストボックスを元にリストボックスにコピーする手続きが欲しくなったときは?
GUIが4種あったら4×4の16種類、copyLinesHogeHogeToFugaFugaを用意しますか?
ここでcopyLinesTextEditとcopyLinesListBoxコードの中身を見直してみてください。
そうです。一言一句同じです。
そんな一言一句同じものを、引数が違うだけなのに全部書くんですか?
そこでインタフェースの出番です。(正確には多態性の出番とするべきでしょうか。インタフェースは多態性を実現するひとつに手段に過ぎません)
言語がインタフェースを持っていて、すべての複数行の文字列を内部に格納するGUIがMultiLineというインタフェースの実装になっていると想像してください。
インタフェースMultiLineには、len
、get
、add
、clear
などが定義されるはずです。
そうであれば、
procedure copyMultiLine(a: MultiLine, b: MultiLine) i: int begin b.clear() for i = 1 to a.length b.add(a.get(i) next end
というひとつの手続きだけがあればすべて事足ります。
ListBoxa
からListBoxb
にコピーしたいならcopyMultiLine(a, b)
と呼べばいいし、
TextEditc
からListBoxd
にコピーしたいならcopyMultiLine(c, d)
と呼べばいいわけです。
copyLinesTextEditとcopyLinesListBoxが別になっている必要はないのです。
インタフェース(やクラス継承)の何が便利なのかわからない、という人の多くは、このような多態を利用した処理の書き方を知らないか、慣れていないように見受けられます。
TextEditやListBoxのような具象を引数に受け取る手続きは想像するのが容易です。しかしインタフェースのような抽象を引数に受け取る手続きが書ける、という想像がしにくいのでしょう。
抽象を引数に受け取る手続きには、それを具象化したものならなんでも渡せます。
copyMultiLineにListBoxもTextEditもどちらも渡せるように。
インタフェースMultiLineの具象であるなら、インタフェースMultiLineで定義されている要素はすべて実装されているという保証があるからです。
インタフェースMultiLineを受け取るような手続きの中では、インタフェースMultiLineで定義されている要素だけしか使えません。しかしインタフェースMultiLineで定義されている要素だけで意味がある一連の手続きが書けていますよね。
そうできるようにインタフェースは定義されるべきです。
考える順番に気をつけてください。
「ある概念を内包する部品」を設計する時、それらは「このような操作を持っているはずだ」という発想が先です。
それをルールとして定義するものがインタフェースです。
GUIを構築するためのプログラムを考えます。
リストボックスとか、プルダウンリスト、コンボボックスを操作する手続きを考えていると、これらは(文字列の取得とか追加とか件数の取得とか初期化とかの)同じような操作が必要なことに気づきます。
それはなぜかというと「順序がある複数の文字列を内部に持つ」という構造が同じだからです。
そう考えると用途は違っても、テキストボックスも同様な構造を持つことがわかります。
たとえ言語にインタフェースが存在しなかったとしても、リストボックスはget(int)
で、プルダウンリストはitem(int)
で、テキストエディットはline(int)
で文字列を取得するようなら、とても変じゃありませんか?
同じ概念を内包するコンポーネントなら、違う手続きで操作するのはよくないです。
同じ手続きなら、違う名前をつけるのはよくないです。
(逆から言うと違う名前の方が相応しいなら、たまたま似ているだけの「別の概念」だと分析するべきです)
それはつまり、言語にインタフェースが存在しようがしまいが、ルールはある方がいいってことです。
言語要素としてのインタフェースは、そういったルールを宣言する、あるいは明確にするのに役立ちます。また、ルールが遵守されていることを保証してくれます。
それが「ルールを強制させる」の意味もしくはメリットです。
投稿2018/06/23 11:31
編集2018/06/26 00:47総合スコア11277
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
インタフェースの利点は機能の向上ではありません。あくまでも、規則づくりです。プログラムが完成し、改修もしないならば、この利点は意味がありません。
この利点は開発途上におけるミスの防止やプログラマ間の連携補助、手間の節約とか作業時間短縮です。
投稿2018/06/23 10:25
総合スコア4853
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
コメントに書いたり、回答にしたりバラバラですみません、コード書くので回答のほうに載せます。
処理を後で変えることもできるんです。
についてですが、以下のサンプルについて説明します。
java
1//元の実行Mainクラス 2public class Main { 3 public static void main(String[] args) { 4 Add cal = new Add(); 5 cal.method2("足し算"); //”足し算をします"の表示 6 cal.method3(); //定数の足し算の結果表示 7 } 8}
最初、上記のように足し算を行う処理があったとしたとき、これを掛け算に変えたい場合変更すべき箇所は
以下の 1,2のみになります。
Addクラスも Multiplyクラスもインタフェースにより method2,method3を持つことが保証 されているため
同じ使い方(引数、返り値)ができるのです。
つまり呼び出す側からしたとき、クラスが変わっても処理の流れや呼び出すメソッド名を変える必要がないのです。
java
1//実行Mainクラス 2public class Main { 3 public static void main(String[] args) { 4 Multiply cal = new Multiply(); // 1.インスタンス化 5 cal.method2("掛け算"); //2. ”掛け算をします"の表示 6 cal.method3(); //定数の足し算の結果表示 7 } 8}
しかしこれだけのサンプルだと1.のところを書き換えなきゃいけないのでまだ実装時メリットを感じられないかもしれません。
本当にこれだと思えるのにはインタフェースと継承を使った デザインパターンを勉強されるとよいかと思います。
投稿2018/06/23 11:15
総合スコア2404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/26 15:29
2018/06/26 16:09
2018/06/27 17:13
2018/07/07 07:55