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

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

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

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

インターフェース

インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

7回答

3334閲覧

インターフェースが使えて何が嬉しいのか?その「メリット」と「デメリット」について

mr0237

総合スコア164

Java

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

インターフェース

インターフェイスという用語はハードウェア・ソフトウェアの両方に使うことができます。 一般的に、インターフェイスは内部処理の詳細を見せないように設定されます。オブジェクト指向プログラミングにおいて、インターフェイスはabstractクラスとして定義されます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

0グッド

0クリップ

投稿2018/06/23 10:01

下記の質問と重複するかもしれませんが・・・・


インターフェースって何のメリットがあるんですか?

インターフェースってわかりやすい例に例えると?


オブジェクト指向を勉強している者です。説明が下手ですいませんが、

インターフェースの定義形式文

↑**これのみを定義(記述)**しておくことで、

0. 「基準(ルール)を定める」
1. 「ルール(規格)を強制できる(ルール違反できない)」

上記のメリットがありますが、そこで疑問があるのですが、

「インターフェース」使えることによる、その**「メリット」「デメリット」**とは何なんでしょうか?

つまり、インターフェース(ルールを強制させる)を使うことで、

「何が嬉しいのか?」
「何が便利になるのか?」

ということです。

そもそも**「ルールを強制させる為にインターフェース使うぞ!」とは思えないはず**です。
**「インターフェース」における本質(の目的)**は何なんでしょうか?

(できれば)日常的に例えたもののほうがわかりやすいです。


さらに・・・

【Java入門】interface(インターフェース)の使い方 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト

↑このサイトに**「インターフェース」を使うメリット**が載ってあるんですが、そこには

でも、具体的に書かないメリットがあるんです。
それは、実際に処理を実行する直前に処理内容を決められるんです。
ということは、処理を後で変えることもできるんです。
後になって、処理を変えたい場合はありませんか?
そんな時に該当する場所をわざわざ探しに行って変える必要がないんです。
これってとても便利ですよね。

(・・・省略)

でもinterfaceを使えば、MultiplyクラスのようにMainクラスと同じファイル内に処理の変更を記述することができます。
探して書き換える手間が省けるのがメリットなのです。
処理が複雑になり記述量が多くなると、多数のファイルに分けて記述するという機会が増えます。
そんな場合はinterfaceでメソッドの型だけ宣言しておいて処理は別で記述する方が、後々の変更などが予想される場合には便利になってくるのです。

↑このように書かれておりますが、

「ルールを強制させる」のと「手間が省ける」

どういう関係があるのでしょうか?


さらに

なぜインタフェースを使うのか?

上記のサイトには「インターフェースにおけるデメリット」が載っており、そこには

中身が空っぽというデメリットは、「委譲」で回避できます。
委譲とは、実装済みのクラスに処理を委ねてしまう(単なるクラス呼出し)です。

と書かれていますが、インターフェースにおけるデメリットというのはこういうことなんでしょうか?(日常的な例えのほうがわかりやすいです。


長文になって失礼しまいますが、回答のほうお願いいたします。

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

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

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

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

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

guest

回答7

0

こんにちは。

そもそも「ルールを強制させる為にインターフェース使うぞ!」とは思えないはずです。

そんなことは全くありません。ルールを強制させるためにインターフェースを使います。
これにより、間違ったルールでクラス・メソッドを呼び出そうとした時、処理系がエラーを報告するので間違いに早期に気がつくことができます。その御蔭で、そのような間違いを犯していないかのテストを省略でき、プログラムの信頼性を保ちつつ納期を短縮できます。

また、同じような機能を持つクラス毎に使い方が一々異なっていると面倒極まりないです。それらのクラスが同じインタフェースを継承していることが分かれば、使い方も同じであることが分かりますから、使う側にとって非常に楽になります。

(できれば)日常的に例えたもののほうがわかりやすいです。

ちょっと前の質問に日常的に例えて回答した記憶があります。

自動車のアクセルとブレーキの操作方法が、現在のほぼ全ての自動車で統一されていることは自動車を運転する人にとって非常にありがたいです。
もしも左がアクセル/右がブレーキのような自動車が合った場合、左がブレーキ/右がアクセルの自動車に習熟している人は、その自動車へ乗り換える時、再習熟訓練をするべきではないでしょうか? そしてちゃんと操作できることを確認した上で運転許可を与えるべきと思います。そんな世界はナンセンスでしょう。
恐らく自動車のアクセルとフレーキの操作方法(インターフェース)は、法律で強制されているのではないかと思います。その御蔭で、我々は自動車の運転方法を1種類学ぶだけでほとんどの普通自動車を運転できます。

プログラミングの世界のインターフェースも同様です。1種類のインターフェースの使い方を学ぶだけで、そのインターフェースを継承している全てのクラスを使えるようになるのですから、本当に楽になりますよ。
更に、多くの自動車と異なり、明らかな誤操作(誤呼び出し)は事前に(コンパイル時に)エラーを出してくれるのですから、至れり尽くせりです。

中身が空っぽというデメリット

これは、「インターフェース」という仕組みを持つ言語における通常のクラスを継承する場合とインターフェースを継承する場合の差の話です。mr0237さんの質問を見る限り、クラスの継承とインターフェースの継承を比較されているようには見えませんので、このデメリットは現在の質問の主旨のデメリットには該当しないと思います。

インターフェースにより使い方を統一し、それを強制することのデメリットは、それが必要な場合にはあまりないように思います。


【追記】
ところで、一般的なインタフェースは「①定数 ②メソッド名」という形式の定義ではありません。
多くの場合「メソッド名とシグニチャ」を定義します。シグニチャは当該メソッドの「戻り値の型、引数の型の並び」を定義する言語が多いです。int foo(int, short, string);などですね。

投稿2018/06/23 10:50

編集2018/06/23 10:58
Chironian

総合スコア23272

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

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

mr0237

2018/06/26 15:29

すいません。それは要約すると、つまり 「ルールを強制させる」ことにより、「使い方を統一する」ことができる=「使いやすくなる」ということでしょうか?
Chironian

2018/06/26 16:09

すいません。ちょっと舌足らずでした。 1.「ルールを強制させる」ことで早期にバグを発見しやすくなる。 2.「使い方を統一する」と「使いやすくなる」
mr0237

2018/06/27 17:13

すいません。再度要約すると、つまり、 「独自規格を統一させる(ルールを強制させる)」ことにより、 ①「規格統一」→使いやすくなる ②「強制させる」→(ミスによる)バグが少なくなる ということなんでしょうか? 何度もすいません。
Chironian

2018/07/07 07:55

規格を統一し、かつ、そのルールを強制することは可能ですが、規格を統一することと、そのルールを強制することは別物です。いっしょくたにするから理解できないのではないでしょうか?
guest

0

  1. インターフェースを実装したクラスは、インターフェースが持つメソッド確実に持っている
  2. インターフェースを実装したクラスはインターフェース型の変数に入れられる

インターフェースを実装する側にメリットが有るのではなく、
インターフェースをを受け取ってなにかする側にメリットがあります。

というわけで、インターフェースを実装する側を眺めててもメリットは全然わかりませんし、
使う側も、インターフェース型の変数なり引数を使わなければただいたずらにコードが増えただけになります。

教科書的な例ですが、画面に文字を出す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()メソッドを持っていないので、当然コンパイルエラーを起こします。

そこでインターフェースを使うとこうなります。
ScreenWriterFileWriter
write()メソッドを持つIWritableインターフェースを実装していたら、

public class Greeter{ public void sayHello(IWritable w){ w.write("HelloWorld"); } }

IWritablewrite()メソッドを持っているのでGreeter側ではこれで問題ありません。
仮に実装クラスでwrite()をうっかり実装忘れしていたらコンパイルエラーにしてくれます。
(これを指して、「メソッドを持つように強制されている」)

そもそも「ルールを強制させる為にインターフェース使うぞ!」とは思えないはずです。

思うんです。
プログラマーが意図しないミスをしたときに、実行時に気づくのではなく、
コンパイルエラー(ここで言うルール)になってくれたほうが
自動でミスを見つけてくれることになるので圧倒的に楽なんです。

「~~Writerっていう名前のクラスなんだからWrite()を持っている」という人間が勝手に決めたことを
コンパイルエラーという形で厳格に守れるようになります。

投稿2018/06/23 10:57

編集2018/06/23 11:09
ozwk

総合スコア13521

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

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

0

ベストアンサー

カセットコンロとそのボンベの規格が、1998年の阪神淡路大震災をきっかけに統一されたことはご存知でしょうか?
それまではメーカーごとに独自の規格を持っていたため、ボンベの貸し借りなどができず、不便な状況になっていたのです。
規格が統一されたことにより、(完全ではありませんが)コンロと異なるメーカーのボンベでも使うことが可能となり、非常に使いやすくなったのです。

これに限らず、DVDやUSBなどはルールを統一しているからこそ、広く利用されるようになったのです。

投稿2018/06/27 16:54

swordone

総合スコア20651

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

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

0

いろいろ答えを書かれていますが、オブジェクト指向に基づいた視点から。Java におけるインターフェースがなぜ作られたのか、という点からアプローチしてみます。

そもそも Java がインターフェースを採用したのは、それまでのオブジェクト指向プログラミングの主力であった C++ における多重継承の問題を回避するためです。
では多重継承とは何か。
通常、オブジェクト指向におけるクラスの親子関係は、1:n になります。あるクラスにとって、親は一つなのです。ところがオブジェクト指向プログラミングを実践するようになって、この 1:n では処理しきれない親子関係が発生することが分かってきました。
※ペット - 犬と、ペット - 猫、ペット - 金魚 のような関係だとして、犬と猫は「鳴く」のですが金魚は鳴きません。なので、共通の親に当たるペットに「鳴く」を付け加えられないのですが、そうすると犬と猫の「鳴く」は別のメソッドになってしまい、多態性が損なわれます

C++ では親クラスを複数にすることで回避しましたが、親が複数いるという状態は別の弊害を引き起こしてしまい、C++ のオブジェクト指向を難解なものにしてしまうことになりました。
上記の例でいえば、もう一つ、ペット - 鳴くペット というクラスを定義し、ここから鳴くペットと犬 - 鳴く犬、鳴くペットと猫 -鳴く猫、のような継承関係(菱形継承)で実装するなどです。
もっともこの程度なら、ペット - 鳴くペットと、ペット - 鳴かないペット として、さらに鳴くペットから犬と猫を、鳴かないペットから金魚を派生させてもうまくはいくのですが、クラス樹形図全体が変わってしまうため、思わぬところに影響が出てしまう可能性があります。これは定義するクラスの数が増えるごとに、また複雑さが増すごとに幾何級数的に増大していくので、破たんしやすいのです。

この反省に基づき考えられたのがインターフェースです。インターフェースでは「鳴く」という動作(メッセージ)のみを定義します。なので、あるクラスに「鳴く」インターフェースを付与する、という形で拡張できるようになっています。
インターフェースは動作(メッセージ)を定義しますから、そのクラスの実装ではかならずその動作を実装しなければなりません(仮に「何もしない」動作だとしても、そういう実装をしなくてはならない)。
※インターフェースの定義そのものは「抽象型」であって、実装をもちません。インターフェースを追加したクラスで、実装をすることになります。

オブジェクト指向プログラミングの歴史を追いかけると、疑問が解消しやすいかと思います。

投稿2018/06/27 00:57

tacsheaven

総合スコア13703

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

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

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には、lengetaddclearなどが定義されるはずです。
そうであれば、

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
quickquip

総合スコア11038

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

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

0

インタフェースの利点は機能の向上ではありません。あくまでも、規則づくりです。プログラムが完成し、改修もしないならば、この利点は意味がありません。

この利点は開発途上におけるミスの防止やプログラマ間の連携補助、手間の節約とか作業時間短縮です。

投稿2018/06/23 10:25

HogeAnimalLover

総合スコア4830

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

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

euledge

2018/06/23 10:55 編集

開発するのが一人で、かつ大きな規模の開発でなければインターフェイス無くてもほぼ問題ないと思います。 前回の質問の回答の中で、インターフェイスは規約でそれをimplementしたクラスの設計を強制する旨を書いたのですが、上位の設計者とクラスの実装する人が分かれていた場合の事を想像してみてください。 上位の設計者はどの様なインターフェイスが必要かを決め、クラス実装者に対してこのインターフェイスを持つクラスの実装をする様に指示することで必要な実装を満たさなければならない事を言語レベルで伝えることが可能です。 これがメリットと考えます。 デメリットとしては単にファイルが増えてしまうことでしょうか。ただ実装はimplementする側にある為、extendsによる継承と比べて実際に何をしているかは追いやすいとは思います。 (今回の質問の中にあるサイトの例では同一ファイルに置くことのメリットを言っていますが、私の経験ではあまりこういうことはやらないでやっぱりクラスごとファイルにしますね) 何でもインターフェイスにすれば良いと言うわけではなく必要と思われる場合に使用する(継承についても同様)のが良いと思います。
guest

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

euledge

総合スコア2404

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問