

カテゴリはJavaですが、オブジェクト指向という観点での質問です。
私はオブジェクト指向を勉強中です。(C#)
そこで、疑問に思ったのがタイトルで示したインタフェースについてです。
以下に疑問を列挙します。
1.インタフェースはなぜ使うのですか?
2.使うメリットはなんですか?
3.インタフェースのインスタンスって作れるのですか?
4.インタフェースは必ずどこかのクラスに継承されないといけないのですか?
単体では何もできないのですか?
5.具体的な使い方を教えてください。
全部でなくてもよいのでわかる方ご教授よろしくお願いいたします。
No.5ベストアンサー
- 回答日時:
インターフェースとは「役割」です。
一般的なインターフェースの命名規則は「~ableを末尾に付ける」とあります。例えば「比較できる」なら「ICompareble」です。
メディア再生ならplay,stop等を持ったIPlayableインターフェースが考えられます。これで動画、音楽、静止画が文字通り「再生できます」。
クラスは実装とインターフェースの両方を継承しますが、これでは不便なことが沢山あります。最も不便なのは、余計なメソッドが沢山付いてくること、多重継承でもしない限り、継承だけでは機能を共有しきれない(多重継承は多重継承で、別の問題がある)事です。
インターフェースにはこの制約がありません。「~ができる」という役割に必要なメソッド群を定義し、その役割を持たせたい複数のクラスに実装させれば良いのです。
また逆に、1つのクラスに複数の役割を持たせることができます。
インターフェースは、引数の型指定に使うと用途がよく分かります。
元のインスタンスが何を継承していようと、インターフェースを通じて操作できるのはそのインターフェースに定義されたメソッドだけ、つまり純粋に「ある役割について操作したい」というメソッドを定義できます。
1.インタフェースはなぜ使うのですか?
継承では制約が多い場面で、特定の「役割」に基づいた操作を定義したいとき、インターフェースを使います。
2.使うメリットはなんですか?
継承より制約が少ないことです。中身が空っぽというデメリットは、「委譲」で回避できます。委譲とは、実装済みのクラスに処理を委ねてしまう(単なるクラス呼出し)です。
3.インタフェースのインスタンスって作れるのですか?
作れませんが、インターフェースの引数や変数に、インターフェースを実装したクラスのインスタンスを代入できます。この辺の使い勝手は普通のクラスと同じです。
4.インタフェースは必ずどこかのクラスに継承されないといけないのですか?
単体では何もできないのですか?
中身がありませんし、それだけではインスタンス化できませんから、YESです。
5.具体的な使い方を教えてください。
理論的な話なら「Javaオブジェクト設計」というペーター・コード氏の著作をお薦めします。
C#での具体例なら、参考URLにプラグインの作り方が載っています。
参考URL:http://dobon.net/vb/dotnet/programing/plugin.html
No.8
- 回答日時:
インターフェースの威力を知りたければ、たとえばストラテジ(Strategy)パターンと呼ばれているデザインパターンのサンプルコードなど一度ごらんになるとよいと思います。
細かいこと言うと、インターフェースが実現するポリモーフィズム(多態性)は、コンパイル時にはインターフェースSの型として型チェックされたオブジェクトが、実行時にはSを実装したクラスのインスタンスなら何でもよいという「ズレ」によって支えられています。インタフェースの効能はというと、
1.多態性(すでにご指摘の)
2.コントラクトが守られているかどうかをコンパイラによってチェックさせることができる。
3.単一のオブジェクトに対して、今問題にしたいひとまとまりの機能一覧を抽象して顕在化させることができる。この時特に「他のインタフェースや実装の詳細は”見えないし、見なくて済む”」
といった諸点にあると思います。
いずれにしろ、JavaやC#をお書きになるならインターフェースを理解しないっていう手はありません。その威力に触れたら、今とは逆にインターフェース中毒になってしまうくらい使いたくってしょうがなくなると思いますよ^^。
No.7
- 回答日時:
いろいろな考え方はありますが、私はつぎのような考え方をお勧めします。
要は、呼ばれることだけに特化した「インターフェース」の定義です。その使用方法を超えるものは class (abstract class も含む)にしたほうが良いです。
ただ、interface は「軽い」ので、コーディングの都合上、本来は class のほうがふさわしいのだけど、便宜上 interface にしてしまう、ということも多いです。
巷の書籍等の解説では interface を過度に使いがちな傾向があると思います。しかし、設計の開始時点では、まずは interface よりは abstract class を使うことを検討されたほうが良いです。その中から interface で済むものを、interface に「降格」させるような感じにすると良いでしょう。
> 1.インタフェースはなぜ使うのですか?
クラスが呼ばれる際の呼ばれ方、および呼び側での呼び方、を定義するためです。
> 2.使うメリットはなんですか?
古いものにたとえると、C の関数ポインタのプロトタイプ宣言に、近いものになります。
interface がないと、コンパイル時にメソッドを呼ぶ時の引数の並びや引数の型が分からないままになってしまいます。実行時にこれらを解決する方法も考えられなくはないのですが、概して面倒になります。
> 3.インタフェースのインスタンスって作れるのですか?
呼ばれ方の定義だけですので、それだけではインスタンスは作れません。まあ、しいて言えば、
class FooClass extends Object implements BarInterface
みたいなことをすれば良いわけですが。
> 4.インタフェースは必ずどこかのクラスに継承されないといけないのですか?
> 単体では何もできないのですか?
呼ばれ方の定義なので、単体で使うということはないです。interface を使うからには呼ばれるクラスがあるはずなので、そのクラスが interface を implements します。
> 5.具体的な使い方を教えてください。
リスナ(listener)が interface の最たる使い方になります。
Button の ActionListener などです。
ご回答ありがとうございます。
unibonさんだけでなく、他の方々にもこの場でお礼を言わせていただきます。
みなさんのお陰で、インタフェースの用途とか使う目的は分かってきました。
ありがとうございました。
No.6
- 回答日時:
他の方々の回答で、ほぼ出尽くしているとは思いますが。
。。> 1.インタフェースはなぜ使うのですか?
> 2.使うメリットはなんですか?
クラスの継承をいわゆる「is-a関係」のみに限定するためです。
決して「(クラスの)多重継承の代用品」ではありません。
(クラスの)多重継承に相当することをやろうとした場合、インタフェースによって同等のことができるためこのような言われ方をすることもありますが、本来の意味はもう少し違うところにあると思います。
> 3.インタフェースのインスタンスって作れるのですか?
作れません。
> 4.インタフェースは必ずどこかのクラスに継承されないといけないのですか?
> 単体では何もできないのですか?
インスタンスが作れないため、インタフェース単体では何もできません。
ちなみに、インタフェースは継承ではなく「実装 (implement)」という言葉を使いますね。
> 5.具体的な使い方を教えてください。
インタフェースを文字通りとらえれば良いのではないでしょうか。
たとえば、円を「描く」、三角形を「描く」、…といったように図形を「描く」という共通の「インタフェース」を用意する場合とか。
もちろん、図形というクラスに「描く」というメソッドを用意しておいて、それを継承するという方法も考えられます。
ここでよく考えてみてください。
「図形」というクラスの意味は何でしょうか。
ただ単に「描く」という操作のみのために、クラスを作る意味は本当にあるのでしょうか。
円を「描く」場合には、「中心座標から半径の距離にある点を結んでいく」という方法を取るのに対して、三角形を「描く」場合には、「三点の座標を順番に結んでいく」という方法を取りますよね。
つまり、「描く」という処理の「実装」方法が異なるわけです。
まさに「異なる処理を同じインタフェースで実装する」ことこそが、インタフェースの本来の姿なのです。
もちろん、他の要素を考えたときに「図形」というクラスが必要だということになるかもしれません。
そうするメリットが大きいのであれば、それでも良いと思います。
インタフェースは、「何でもかんでもクラスを作って継承させれば良い」といういい加減な設計をさせないための指標の一つであると言っても良いかもしれません。
インタフェースについては「Java には多重継承がないから、その代用品としてインタフェースが存在する」というような、いかにも Java の欠陥 (?) を補うものであるような言われ方をすることもあるようです。
しかし、わざわざクラスを新たにクラスを作らなくてもインタフェースで十分間に合うことも多いはずです。
いずれにしろ、設計段階でこのあたりの話を整理できていなければ、まともなプログラムにはならないと思います。
こんな感じで、いかがでしょうか。
No.4
- 回答日時:
他の回答者より本質的な話をしてみたいと思います。
C# や Java は「静的な型付け」を行う言語です。「型」というのは、あるオブジェクトがどのようなメソッドやフィールドを持っているか、ということです。そして、静的な型付けというのは、コンパイルの時にプログラム内のオブジェクトの型が正しいかどうかを (ほとんど) 全てチェックすることを言います。
逆に、JavaScript はオブジェクト指向言語ではあっても「動的な型付け」を行います。動的な型付けを行う言語では、オブジェクトの型が正しいかどうかはプログラムが実際に実行されるときにチェックされます。動的な型付けを行う言語には、インタフェースという言語機能は普通は存在しません。
さて、C# は静的な型付けの言語だといいました。そこで、コンパイル時の型のチェックがどのように行われるか簡単な例をあげてみましょう。文字列から Substring メソッドで一部を取り出します。
string s = "abc 123 xyz";
string t = s.Substring(4, 3);
ここで、変数 s に対して問題なく Substring メソッドが使えるのはなぜかを考えてみると、コンパイラはここで次のような三段論法を使っています。
1. 変数 s の型は string クラスである。
2. string クラスには Substring メソッドが定義されている。
3. よって、変数 s に対して Substring メソッドを呼び出すことが出来る。
したがって、コードを次のように書き換えるとコンパイルできなくなります。
object s = "abc 123 xyz";
object t = s.Substring(4, 3);
なぜなら、「object クラスには Substring メソッドが定義されている」が成り立たないからです。
ここで、三段論法の一つ目の命題に注目してみます。
「変数 s の型は object クラスである。」
ここでは、オブジェクトの型は object というクラスによって規定されているので、object クラスで定義されているメソッド (ToString など) を変数 s に対して使うことはできます。しかし逆に言えば、object クラスで定義されていないメソッドは使えません。
上の例では、変数 s の実体は string オブジェクトであるにもかかわらず、object クラスという型に阻まれて、Substring メソッドを使えないわけです。
というわけで、静的な型付けの言語では、オブジェクトのメソッドやフィールドを使うためにはそのオブジェクトの型がとても重要なのです。
さて、上のコードでは string オブジェクトを object 型の変数に代入しました。つまり、子クラスのオブジェクトは親クラスの型の変数に代入することができます。
では あるクラスのオブジェクトをその「いとこクラス」の型の変数に代入できるでしょうか。残念ながらできません。子クラスのオブジェクトは親クラスのオブジェクトの振りをすることができますが、いとこ同士だとそうとは限らないからです。
では、遠い親戚 (または、赤の他人) 同士が同じメソッドを持っているときに、たとえクラスに親子関係がなくても 同じ型として扱うにはどうすればいいのでしょうか。
親子関係という制約があるのは、クラスによって型が決められているからです。そこで、クラスとは異なるものによって型を決めるようにすれば問題を解決できます。それがインタフェースです。
例えば、string クラスには CompareTo というメソッドがあって、二つの string オブジェクトを比較できます。また、int 構造体にも CompareTo というメソッドがあって、二つの int 値を比較できます。string クラスと int 構造体には親子関係はないので、そのままでは string のオブジェクトと int の値を同じ型で扱うことはできません。
しかし、どちらも CompareTo メソッドが使えるという点では共通しています。そこで、IComparable というインタフェースを作り、string クラスと int 構造体はそれぞれ IComparable インタフェースを実装するようにします。IComparable インタフェースには、「CompareTo メソッドがある」ということだけが書かれています。
こうすることで、クラスに親子関係がなくても、それぞれのオブジェクトを IComparable という一つの型で同じように扱うことができるようになります。
参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=1570935
No.3
- 回答日時:
インタフェースは、クラス間の依存性を低めることができます。
言い換えると、インタフェースを使うと、実装クラスがなくてもインタフェースを使うクラスを作ることができます。
例
AaaクラスがBbbクラスを使うプログラムを作るとします。AaaクラスがBbbクラスを使うとは、たとえば
void foo(Bbb b)というメソッドがAaaクラスにあるということです。
また、Bbbクラスには
void bar(int i)
見たいなメソッドがあって、foo() から bar() を呼び出すことになるとします。
このとき、Bbbがクラスである場合、Aaaのソースコードをコンパイルするには、Bbbクラスのコンパイルが終わっていなければなりません。
Bbbクラスが複雑で、開発に時間がかかる場合はダミーのBbbクラスを作らなければなりません。
では、Bbbをインタフェースにしたらどうでしょう。
Bbbは void bar(int i)の宣言だけでいいのですぐ作れます。
Aaaは、Bbbインタフェースがあるのでコンパイルもできます。テスト用には Bbbを実装した BbbStab スタブクラスでも作ればいいでしょう。
ダミークラスではないので、本物の実装クラスができたときに上書きする必要もありません。
No.2
- 回答日時:
もともとオブジェクトの継承には2つの側面があります。
その一つがインターフェースの継承であり、もう一つが実装の継承です。
classはこの継承の両方を実現しますが、interfaceはインターフェースの継承のみを実現します。
interfaceを使うのは多重継承の実現のためです。実装の継承を含めた多重継承の実現は言語仕様としてもコンパイラの実装としても複雑になり難しいため、これを避けるために多重継承はインターフェイスの継承のみとし、そのためにclassとは別にinterfaceを用意しています。
No.1
- 回答日時:
C#の話(javaも概ね同じ)で(おおざっぱな話なので話半分で)
1.インタフェースはなぜ使うのですか?
2.使うメリットはなんですか?
・多態性を実現する
・抽象クラスを書くより記述が楽できる
・抽象クラスと違って多重実装、多重継承ができる
3.インタフェースのインスタンスって作れるのですか?
インターフェースのインスタンスは作成できないが、
インターフェースをデータ型とする変数などを宣言することはできる。
(インターフェースを実装したインスタンスを代入でき同じメソッドを使用できる(多態))
4.単体では何もできないのですか?
抽象メソッド(インターフェースとしてのメソッド)しか持たないので
実装されないでは、インスタンスも作れないし、何も(?)できない
5.具体的な使い方を教えてください。
面倒くさいので、
ここのサイトからインターフェースを使っているもの(java)を紹介
http://okwave.jp/kotaeru.php3?qid=1250952
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- CPU・メモリ・マザーボード Socket AM4マザーに、レガシーなインタフェースが多数あるのはなぜ? 3 2023/02/17 10:47
- 電気・ガス・水道業 ダイナミックマイクと、コンデンサマイクについて教えて欲しいのですが、PCなどはコンデンサマイクに対応 5 2022/08/15 07:13
- Java オブジェクト指向プログラミングの実践本を紹介してください 3 2022/09/19 04:56
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/05/21 02:41
- その他(プログラミング・Web制作) RaspberryPi Pico MicroPythonでLCDを使うことについて 1 2023/04/20 09:04
- その他(プログラミング・Web制作) LCD ディスプレイを Raspberry Pi Pico に接続する 1 2023/04/25 16:31
- その他(プログラミング・Web制作) I2C接続のLCDディスプレイを使う 2 2023/05/01 17:15
- C言語・C++・C# C# 継承の問題で programに示された拡張をすべて含んだ上で,クラス Mammal に,そのオ 1 2022/07/22 09:48
- Excel(エクセル) エクセル VBAの構文について 2 2023/02/10 18:26
- 英語 canとcouldの疑問形や否定形の可能性の比較について 3 2023/07/05 11:25
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C# 「データが失なわれる可能性...
-
「継承されたメソッドの可視性...
-
デバックログの出し方
-
ゲッターを使わないで変数にア...
-
VB DLLプロジェクトについて
-
レコード件数の表示
-
「タイプ初期化子が例外をスロ...
-
Java初級 引数に適用できません
-
PreparedStatementのレスポンス...
-
VB.NETでフォーム上にExcelのよ...
-
mainメソッドのthrows節で設定...
-
そんなにお金がなくても年に1度...
-
エクセルVBAで、条件に一致する...
-
private static という変数の修飾
-
どこからも呼ばれていない無意...
-
変数名の付け方
-
インスタンス参照でアクセスで...
-
配列のメソッド
-
java eclipse 型に解決できません
-
VBA 同じ名前のオブジェクトを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C# 「データが失なわれる可能性...
-
「継承されたメソッドの可視性...
-
(vba)他のアプリケーションの右...
-
【C#】クラスのコンストラクタ...
-
VB DLLプロジェクトについて
-
メソッドの引数にクラス名を渡す
-
「ラッパークラス」の存在意義...
-
interface,extend,implementの...
-
c++でのヘッダーファイルの循環...
-
このエラーメッセージの意味を...
-
委譲って何ですか?
-
ゲッターを使わないで変数にア...
-
Javaのインスタンス化の構文の...
-
ファイルパスが取得出来ない(P...
-
ASP.NETでの共通コードの書き方...
-
Commons-Discovery.jarとは?
-
デバッグ時に「Source not found」
-
JTextFieldの入力制限
-
JavaのimplementsをC言語で例え...
-
オーバーライドとラッパーの違い
おすすめ情報