電子書籍の厳選無料作品が豊富!

Javaを勉強しております。

インターフェースの使い方を知ったのですが、その利点がわかりません。
インターフェースの記述の仕方はクラスによく似ていますが、インターフェースでできること(フィールドやメソッドを書く)はクラスでもできると思います。
インターフェースでしかできないことはあるのでしょうか?
インターフェースはどのような場面で活用するのが有効なのでしょうか?

A 回答 (7件)

#6です。

ちょっとだけ、訂正。


はたまた

 public void actionPerformed(ActionEvent event){
  if( /* getSource()の戻り値の内容が、あるコンポーネントクラスCのインスタンスと同じ時 */ )){
   // イベントハンドラクラスAにおいて、処理される内容をここに記述。
  }
 }

というようになっているかもしれません。


のコメント文の所を、


はたまた

 public void actionPerformed(ActionEvent event){
  if( /* getSource()の戻り値の内容が、あるコンポーネントクラスCのインスタンスと同じ時 */ )){
   // イベントハンドラクラスCにおいて、処理される内容をここに記述。
  }
 }

というようになっているかもしれません。


に変更。
    • good
    • 0

概念的な事に関しては、もう一通り出揃ったと思いますので、私の方からも同じく具体例でいきます。



>インターフェースでしかできないことはあるのでしょうか?
イベントハンドラ

>インターフェースはどのような場面で活用するのが有効なのでしょうか?
抽象化や再利用性を高めたい時。

Swingプログラミングを行っていく上での便利な機能の一つに、「イベントハンドラ」というのがあります。(J2MEにて有名なiアプリやMIDletなどでも、基本的には同じです。)実際には、J2SEにてイベントハンドラを実現するためには、以下のような手順となります。

(1)イベントハンドラが行われるクラスにてActionListenerインターフェースを実装する。
(2)各コンポーネントクラスのインスタンスに、addActionListenerメソッドを使用してアクションリスナーを設定する。
(3)actionPerformedメソッドをオーバーライドして、実際にイベントが発生した時に行われる処理を実装する。

詳細なプログラムが見たい方は、以下のサイト内の赤文字の部分などを参考にしてください。

JavaでHello World > Swing(イベント)編
http://www.hellohiro.com/swingevent.htm

ここで重要な事は、オーバーライドされたactionPerformedメソッドの中身が、各々のJavaアプリケーションによって違うという事です。例えば、

 public void actionPerformed(ActionEvent event){
  if( /* getSource()の戻り値の内容が、あるコンポーネントクラスAのインスタンスと同じ時 */ )){
   // イベントハンドラクラスAにおいて、処理される内容をここに記述。
  }else if( /* getSource()の戻り値の内容が、別のコンポーネントクラスBのインスタンスと同じ時 */ ){
   // イベントハンドラクラスBにおいて、処理される内容をここに記述。
  }
 }

というようになっているかもしれませんし、はたまた

 public void actionPerformed(ActionEvent event){
  if( /* getSource()の戻り値の内容が、あるコンポーネントクラスCのインスタンスと同じ時 */ )){
   // イベントハンドラクラスAにおいて、処理される内容をここに記述。
  }
 }

というようになっているかもしれません。実際には、Sun Microsystems, Inc.の人達にとっても、どのようなイベントが発生し(Buttonを押したりとか、ComboBoxのいずれかを選択したりとか・・)、その事によってどういったような処理を行うのかなどについては、知ったこっちゃないわけですよ(業務レベルによれば仕様だったりとか、社外秘に絡んできたりすることなので)。ただ、「とりあえず、大元の枠組みに関しては用意しておきましたので、後は担当されているJavaプログラマーさん、詳細な実装の方をよろしくお願いします。」って事なんですよ。

これが、他の回答者さんも述べられていた「宣言と実装を分離」ということなんですね。

参考URL:http://www.techscore.com/tech/J2SE/UI/3.html
    • good
    • 0

分かりやすいかどうかはともかく、例を挙げてみます。


例えば、あるシーフードレストランで「フグを材料にしてディナーを作る」
という企画があったとします。

class Restaurant{
 //ディナーを提供する
 Dinner serveDinner(Zairyo hugu){
  //ディナー
  Dinner dinner;
  //ここでディナーを作る作業があって、その結果ディナーができる
  
  //ディナーを返す
  return dinner;
 }
}
ここで、ディナーを和食にするか、フレンチにするか(フレンチでフグがあるかどうかは知らないけど)
まだ決まってない場合、これ以上メソッドが書けず、このメソッドは未完成のままです。
でも、ディナーを作るには「フグが調理できる」ことが必要で、和食でもフレンチでも変わりません。

そこで、「フグが調理できる」インターフェースを作ります。
interface HuguCookable{
 Dinner makeDinner(Zairyo hugu);
}
これがあれば、さっきのメソッドはとりあえず完成します。
class Restaurant{
 HuguCookable cook; //フグが調理できるコックさん
 
 //ディナーを提供する
 Dinner serveDinner(Zairyo hugu){
  //ディナー
  Dinner dinner;
  //ディナーを作る
  dinner = cook.makeDinner(hugu); //実際にcookが誰かわからないけど、これでディナーは完成!
  //ディナーを返す
  return dinner;
 }
}

あとは、cookに和食の料理人でもフレンチの料理人でも何でもいいので、
「フグが調理できる人」(つまり、HuguCookableをimplementsしたクラス)なら、
ディナーを作ることができるようになるのです。
和食やフレンチだけでなく、中華やイタリアン(イタリアンでフグ?)であろうと
「フグが調理できる」コックさんなら、ディナーを作ることができるのです。
    • good
    • 2

PeterCordの「Javaオブジェクト設計」当たりを読むと良いのですが。



設計の場合、インタフェース中心で考えると楽です。例えば「読み込んだデータを配列にして返す」機能を考えるときは、

・読み込み元は、ストリームから
・配列は、IDataObjectインタフェース
とざっくり決めて、IDataReaderインタフェースをデザインします。

interface IDataReader {
public void IDataObject[] Load(InputStream input);
}
クラスの継承とかはこの時点で考えません。単一継承しかできないJavaでは継承構造は慎重に考える必要がありますが、インタフェースはいくらでも可能なので、「まずはインタフェースで」設計します。
#ジェネリックが使えるならさらに柔軟になりますが

インタフェースの利点は、クラスがもつ制約に縛られずに設計が出来ることです。
逆にそれがデメリット(実装を共有できない)になる場合もありますが、その辺は委譲や継承でなんとかします。

ネットや書籍で調べるなら、「委譲」をキーワードにしてみてください。
    • good
    • 1

Javaは詳しくないのですが・・・



No.2さんの回答のとおりで、宣言と実装を分離させるのが目的ですね。
ソフトウエアの開発中、あるいは完成後に仕様変更が発生したとき、「この変更はどれだけのモジュールに影響を与えるか」って検討する場面が多いです。このとき、個々のソースコード詳細を追いかけるのは大変です。でも、信頼あるインターフェースが明記されていれば、影響範囲の調査作業が軽減されます。それは、実装コードが1行も完成してなくても、可能になります。

また、プログラムの設計においても、単なる要求機能を記述したドキュメントよりも、インターフェースまで記述するのなら、あまりいいかげんな設計はできません。

つまりは、設計精度、開発効率、保守効率などをアップするために必要なものだと思います。
もし全てを1人で開発するなら、不要なしろものかもしれませんね。

ちなみに、(現在は)少人数開発がメインのRuby on Railsだと、クラスはあっても、インターフェースは登場しません。いくらメリットがあろうとも、「似たような作業は繰り返さない」という原則に反するのでしょうね。
    • good
    • 1

インターフェースは宣言とその実装を分離させること自体がそもそもの目的なので


一般的なクラスとの実装可否を比較するのは少し間違っています。
インターフェースとクラスの決定的な違いは、実装内容を自身が知っているか知らないか、という点です。

と、少し教科書のような内容を記述しましたが、なかなか理論的に理解するのは難しいと思います。
ましてやよくある例え話などで理解してもそれは実践からは程遠いです。

・入力値をAというファイルに出力する。
・入力値をBをいうファイルに出力する。
呼び出し側はこのどちらかをメソッドとしてcallするわけですが
その実装内容までを呼び出し側が知る必要はないですよね。
であれば同じインターフェースを持った実装クラスを作成し、あとはそのクラスに任せてしまう。
このように「値を出力する」という宣言部と「どのように出力するか」という実装部を分離させるためにインターフェースが存在します。

本末転倒な思考ですが、上記のような作りになっていれば
・呼び出し側の実装
・Aクラス(Aファイルに出力)の実装
・Bクラス(Bファイルに出力)の実装
と、それぞれ別の開発者が実装を分担することもできます。
    • good
    • 1

Javaは多重継承を認めていませんが、多重継承を行った方がClassの構造がきれいになるなど利点が欠点を勝るときに多重継承の代わりに使うことが多いです。

    • good
    • 4

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!