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

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

ただいまの
回答率

90.50%

  • オブジェクト指向

    286questions

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

  • オブジェクト

    92questions

    オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

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

解決済

回答 16

投稿

  • 評価 5
  • クリップ 17
  • VIEW 17K+

mr0237

score 143

JAVAを勉強している者です。説明が下手ですいませんが、「インターフェース」って何のメリットがあるんですか?
インターフェース」は

派生化してその目的に特化したそれぞれのクラスを統一しておくことでそれらのクラスを気にしなくても、使うことができるもの

とか

派生化したそれぞれのクラスが、その中身を気にしなくても統一して利用できるようにするためのもの」(説明が下手ですいません。)

らしいですが、そんなことして何のメリットがあるんですか?開発が短縮されるんですか?

バラバラな(派生化してその目的に特化した)クラスを統一するなら、最初からきちんと完璧に設計すれば早いと思うのですがどうでしょうか?

わかりやすいような例や例えで教えてくれませんか?  

よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 16

+29

すでに回答が出揃ってる感ありますが、僕も初学の際に同じような疑問を持っていたので、僕なりにわかりやすくお伝えできて、少しでもお役に立てればと思ったので回答させていただきます。

前提

以下のようなアプリケーションであればインターフェースを利用するメリットはほとんどありません。

  • 一人で開発するアプリケーション
  • 一度作って終わる(作った後一切変更をしない)アプリケーション
  • レイヤ化(MVC等)する必要のないアプリケーション

故に、上記ではないアプリケーションの開発を対象として説明させていただきます。(ほとんどこのケースですが・・・)

説明

何のメリットがあるんですか?

【Who】
主にインターフェースのメソッドを利用する人にメリット

【When】
インターフェースの実装が増えた時にメリット

【What】
インターフェースの実装が増えても利用者はそれを意識せず形式的に利用できるというメリット

【Why/How】
例を踏まえて後述

開発が短縮されるんですか?

長期的な目線で見ると短縮されることがあります。
一発ものでは、ファイルを余計に作成することになるので逆に開発は長くなります。

バラバラな(派生化してその目的に特化した)クラスを統一するなら、最初からきちんと完璧に設計すれば早いと思うのですがどうでしょうか?

将来的に起こりうる変更を予測して、最初からきちんと完璧に設計できるのであれば、それに越したことはありません

わかりやすいような例や例えで教えてくれませんか? 

一般的に、インターフェースとは「契約」と言われることが多いです。
日常生活で身近な契約って何だろて考えたときに、電力会社との契約とかがわかりやすいかなと思います。
電力会社と契約済みであれば、極端ですが「電気ちょーだい」というと電気が供給されると思います。
この時、供給された電気はどこでどのように生み出されたのか意識したことはありませんよね?(原子力発電なのか、火力発電なのか、風力発電なのか)
そして、もしかしたら、将来的に原子力発電は廃止されて、それに変わる新たな発電方式が生み出されるかもしれません。その場合でも今まで通り「電気ちょーだい」というと電気が供給されるはずです。
このように、利用者は、契約(インターフェース)によって、電源(実装)を意識しなくても、形式的に電気(メソッド)を利用することができます。これがインターフェースの主な存在意義だと思います。

では、その考え方が、具体的に実務でどのように活かされているのかを、簡単な例にはなりますが記載させていただきます。
ちなみに以降は、レイヤ化アーキテクチャ(MVC等)の知識が前提になります。

それでは、簡単なTODOを管理するアプリケーションを開発する場面を想像してください。(TODOだとCRUDが基本ですが、ここではReadにフォーカスします)

  1. まずTODOのデータを保存する場所を考える必要がありますよね?最初はコストを抑えて、この保存先にはオープンソースのRDBMSを選んだとしましょう。
  2. そうすると、少なくとも、リクエストをコントロールする「クラスA」の作成と、RDBMSに対してTODOデータCRUDするメソッドを持った「クラスB」を作成すると思います。
  3. そのまま、「クラスA」と「クラスB」との間にインターフェース(契約)を設けないでアプリケーションを作り上げたとします。
  4. しかし1年後、オープンソースのRDBMSに深刻な脆弱性が見つかり、それを使い続けていくことが難しくなったとします。
  5. そこで、高速でセキュアな無料で使えるクラウドのデータストレージサービス(以下「クラウド」)があったとして、それに移行することを決めたとします。
  6. そうすると、クラウドに対してTODOデータをCRUDする「クラスC」を作成することになると思います。
  7. そのため、「クラスA」は、「クラスB」と同様に「クラスC」がデータをどこから取ってきて、どういう型で返却してくるかを知る必要があります。

つまり、「クラスC」の戻り値の型が保証されていないので、「クラスC」のテストに加え、「クラスA」のテストも必要になりますし、場合によっては、「クラスA」を修正することになります。

もし「クラスA」と「データをCRUDするクラス」との間に、最初から共通のインターフェース(契約)があれば、データの取得元は変わっても戻り値の型は保証されるので、「クラスA」は「クラスC」の実装を知る必要がありませんし、この先、ファイルに対してCRUDを行う「クラスD」、NoSQLに対してCRUDを行う「クラスE」、メモリキャッシュに対してCRUDを行う「クラスF」・・・が現れても、「クラスA」との間にインターフェース(契約)がある以上、「クラスA」は全く実体を意識する必要はありません。また、多くの場合「クラスA」に影響はありません。
上位レイヤーの「クラスA」は、下位レイヤーの「クラスB・・D」がどんな実装をしてどこからデータを取ってこようが、同じ型の値を契約どおりに返してくれれば、「クラスA」に変更が加わることは原則ありません。

実用例の一部を紹介してきましたが、前述の通り、役割ごとにカテゴライズされた各レイヤー間にインターフェース(契約)を設けることによって、各レイヤー間を疎結合にし(依存度を低くし)、変更に強いアプリケーション作ることができる
これがインターフェースを利用する最大のメリットと言っても過言ではないと思います。

補足

インターフェースのメリットを最大限に活かす仕組みとしてDependency Injection(依存性の注入)というデザインパターンがあります。
少々複雑な上、質問に対する回答にはならないのでここでは触れませんが、インターフェースを理解された次のステップとして、知っておくと良いと思います。

投稿

編集

xenbeat

xenbeat

Docker総合1位

score 2603

  • Docker総合1位
  • Symfony総合1位
  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • yuba

    yuba

    2017/03/26 09:07

    以前、エンジニアのレベルを問う質問の1問目として「インターフェースのメリットを一言で説明せよ」というのを挙げておられた方がいて、その方の模範解答が「疎結合の実現」だったなというのを、補足でDIに触れられているのを見て思い出しました。
    http://d.hatena.ne.jp/iad_otomamay/20130318/1363596244

    キャンセル

  • MasahikoFukui

    MasahikoFukui

    2017/03/28 14:34 編集

    すみません。
    書くところ間違えました。

    キャンセル

checkベストアンサー

+20

未来のことを考えてください。

今完璧に設計しても、世の中の法律が変わるとかお客さんの要望が変わるとか、さまざまな要件でコードには見直しがかかるときがあります。
インターフェースとはそのときに備えておくためのものです。
こちらが参考になるかもしれません。

ここから具体例を書いてみましょう。長くなりますので読まなくても構いません。

家電製品を考えてみます。

【問題になるようなパターン(インターフェースなし)】

1.ドライヤーを作った
2.電子レンジを作った
3.冷蔵庫を作った

それぞれは共通のコンセントを持っていますので、一つの電源タップで利用することができるとします。

4.新しい電化製品、テレビが発明された。

ここでこのテレビという製品は、新製品であるがためにコンセントの形が独自に作られていたとします。
そうすると従来の電源タップで使うことができません。変換機を買ってきたり、場合によっては家を工事する必要があるとします。
せっかくの新製品なのに、うまく使えず家庭の皆さんはさぞ怒ったことでしょう。また売るほうとしても工事が必要とあっては売れ行きに響くかもしれません。

これがインターフェースが統一されていないということです。

【上記問題を解決するようなパターン(インターフェースあり)】

0.コンセントの規格が決まり、電化製品は基本的にはその規格に沿ったコンセントを作る必要があることになった(インターフェース)
1.ドライヤーを作った
2.電子レンジを作った
3.冷蔵庫を作った
4.テレビが発明された

ここで上記の家電製品のコンセントの形が全て統一されていれば、全て同じ電源タップが使えますね。変換機を買ってきたり、工事をしてコンセントの形を変えたりなどということは不要になります。
逆に言えば、家電製品の開発者は「コンセントの形を統一する必要性に迫られる」ということになりますが、それがインターフェースの本質です。

CDを買ったことはありますか?いろんなレコード会社から出ているCDは、統一されたCDプレイヤーで聴くことができますね。それはCDというインターフェースに合わせて各会社がCDを作っているからです。何もCDプレイヤーを買いなおす必要はないわけですが、それは各会社がわざわざ努力している賜物です。
AndroidとiOSは充電に使うケーブルの形が違いますね。あれは規格が違うからです。ユーザーからすれば、統一されていたほうが便利だと思いませんか。企業戦略ゆえ仕方のないことですが、2本も使い分けしたりしたくはないですね。

投稿

akabee

akabee

AngularJS総合1位

score 1800

  • AngularJS総合1位
  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+4

実は僕も、(欠点は多いですが)「多重継承でいんじゃね?」と思ったことがあります。

まずインタフェースのインプリメントと、クラスの継承の違いから考えると。
クラスの継承は、そのクラスの本質的な機能を受け継ぐことです。
対して、インタフェースの実装はそれ以外の機能を参照するための「口」を作ることです。

実のところ、デリゲーション(移譲)モデルを理解しないで、インタフェース継承だけ使っても旨味は薄いです。
というか、C++の多重継承とどう違うのかさえ理解しづらいです。

さらに言えば、インタフェースは継承した側から見れば「機能の拡張」ですが、参照する側から見れば余計なメソッドや属性をいじらせないための「機能の制限」(=他の人のコメにも書いてある通り「疎結合」ってやつですね)と言う側面もあります。まさに「インタフェース」です。

そういった事が理解できた頃から「なるほど合理的だ」と思えてきたものです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

例:コンセントとプラグ

世の電源プラグが規格がバラバラだったとして、

この部屋のコンセントは、とある掃除機の電源プラグにしか適合しません。
別の部屋のコンセントは、とあるテレビの電源プラグにしか適合しません。

などと言われたら不便ですよね?

そこで電源プラグにインターフェースを定義してやれば
コンセント側は何が刺さっているかは気にせずに電力供給できるようになりますね。

もちろん最初からちゃんと"設計"して、ここにはこの機械しか置かないと決めれば
インターフェースがなくても問題ないですが、
これが賃貸住宅などだったら柔軟性がなくて使う側が困りますね?

基礎的な仕組みだけ提供し、後は使う側が決めてくださいというときに
インターフェースは役立ちます。
プログラム的には、フレームワークなんかがそうですね。


例:加速度センサーをつかって歩数計を作る

加速度センサークラスなるものが存在するとして、
歩数計クラスは加速度センサークラスから値を取ってきて
いろいろ処理して歩数を計算するとします。

さて、不具合が起きたときの調査用に、
加速度センサーのログを模擬入力として歩数計を動かしたく思いました。

安直なのは歩数計クラス内に、

if(調査モード)
    acc = ログファイル.値を取ってくる();
else
    acc = 実機.値を取ってくる();

(歩数判定の処理)

などと書くことです。

しかし、これだと、歩数計クラスが歩数判定以外のことをしてしまい、コードの見通しが悪くなります。

そこで、加速度センサーインタフェースを作成し、
実際のセンサーと、ログファイルによる模擬はこのインターフェースを実装させます。

歩数系クラスはインスタンス作成時に
加速度センサーインタフェース(を実装したクラスのインスタンス)を渡せば

acc = センサー.値を取ってくる();

(歩数判定の処理)

と歩数計クラス内で歩数検知に関係ないコードが減ります。

投稿

ozwk

ozwk

score 5704

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • yuba

    yuba

    2017/03/26 09:10

    実例のほう、これはインターフェースのメリットではなくて段階的詳細化というか責務を関数にまとめることのメリットについてのものになるかと思います。

    キャンセル

  • ozwk

    ozwk

    2017/03/26 10:33

    歩数検知と加速度取得の具体的な方法をDI的に切り離す例のつもりだったんです。

    キャンセル

+3

javaの入門書を読んでいた時は私も同じようなことを思っていました。
インタフェースって何の意味あるの?使うことあるの?

時は経ち、初心者ではなくなって、色んなライブラリやフレームワークを使っているうちに、
インタフェースって便利、と思えるようになりました。

実例がないと理解しづらいですが、初心者のうちは実例を理解できるレベルにないと思うので、
理解に時間がかかりそうなところは読み飛ばして、
経験を積んだ後に読み返してみると、スッと入ってくると思います。

投稿

lightwill

lightwill

score 818

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

>>最初からきちんと完璧に設計すれば早い
これは理想論です。実際はなかなかその通りにはいきません。契約や設計初期における技術実働部門の発言権は大きくない場合が大半です。逆に、汎用的なユーティリティを作成する段階では、アプリケート側の都合を考慮しきれない場合もあります。

たとえば、ArrayListとLinkedListはどちらも可変長リストを実現しますが、向き不向きがあります。要素の追加削除が多いならばLinkedListの方が向いていますが、ランダムアクセスをするならばArrayListの方が向いています。このようば場合、プログラミングの段階においてはどちらにすれば良いのか確定しないことは多々ありえます。このような場合はインタフェースを使っておくと便利です。

投稿

編集

HogeAnimalLover

HogeAnimalLover

score 2843

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

こんにちは。

らしいですが、そんなことして何のメリットがあるんですか?開発が短縮されるんですか?

開発期間の短縮効果は確実にあると思います。

Javaはあまり知りませんが、例えばC#は列挙できるクラスはIEnumerable<T>インタフェースを継承しています。多くはコンテナですね。
ある日、IEnumerable<T>を継承したコンテナを使って列挙処理を書いたとします。その人はそのためにIEnumerable<T>の使い方を学んだことでしょう。
その日以降、その人はIEnumerable<T>を継承したコンテナ全ての列挙処理を書けるようになります。
特に新人さんにとってはかなり有り難い話と思います。

また、クラスの外部インタフェースをドキュメントだけで記述するより、インタフェースを定義することで厳密に記述でき、かつ、強制も容易なため、再利用性の改善や結合テスト時の不具合削減効果もあると思います。

投稿

Chironian

Chironian

C++総合1位

score 18416

  • C++総合1位
  • C総合1位
  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

わかりやすい例を挙げるなら、HTMLのDOMノードもよい例だと思います。

<DIV>
  <P>
  <BR>
</DIV>
<DIV>
  <A></A>
</DIV>

HTMLの内部を調べる方法の一つにこれらのタグの階層をDOMとして表現し、そのノードを辿るということはよく行われます。DOMではDIV,P,BR,AなどのHTMLタグは全てElementというDOMノードで表現されます。その一つ下の階層を辿るにはElementインターフェースのchildというメソッドで辿れることになっています。(メソッド名などはクラスライブラリーによって違うかもしれませんがそのあたりは気にしないでください)

さて、Elementという共通のインターフェースがなかったとしたら・・・

DIV.getChildOfDiv
P.getChildOfP
A.getChildOfA
...
etc.

こういう似たようなことをするgetChildOfナンチャラメソッドを沢山用意し、今見ているノードの種類ごとに「一つ下の階層を調べる」コードを書くのに以下のような似たコードを大量生産しなければなりません。

switch (typeof(currentNode)) {
case DIV: return ((DIV)current).getChildOfDiv;
case P  : return ((P)current).getChildOfP;
case A  : return ((A)current).getChildOfA;
...
}

そんなことをするよりこれらの全てのノードはElementという共通のインターフェースを持つと定義して

currentNode.getChild

の1行で済ませてしまうことの方が優れた設計にできる・・・

こういったことがインターフェースの意義です。

投稿

KSwordOfHaste

KSwordOfHaste

Swing総合1位

score 15376

  • Swing総合1位
  • Scala総合1位
  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

実例で行きましょう。

Readableインターフェイスは、readメソッドを持つインターフェイスです。

これを継承するクラスは下記のものがあります。
BufferedReader, CharArrayReader, CharBuffer, FileReader, FilterReader, InputStreamReader, LineNumberReader, PipedReader, PushbackReader, Reader, StringReader

文字列を取得して処理するメソッドの引数には、Readableインターフェイスを指定すれば、上記のいずれのクラスであろうと、一つのメソッドで動作が可能です。

もし設計を頑張ってReadableクラスとしてすべての継承元のクラスを取り込んだ巨大なクラスを作ったとしたら、おそらくメンテが効かず、入力の形式が増えたときの対応は難しくなるでしょう。

また、StringReaderクラスにはCloseableインターフェイスがありますが、CharBufferクラスにはありません。

このような複雑な違いを吸収する設計を事前に行うには、相当の思慮とコーディングが必要になります。

もちろんインターフェイス設計を間違うと継承先のすべてのクラスに影響しますので注意が必要ですが、影響範囲を狭くすることで、設計の問題を少なくすることが出来ます。

投稿

iwamoto_takaaki

iwamoto_takaaki

score 2627

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

私の答えは恐らく少数派で、反論が出ると思いますが...  Jave,C#は多重継承がないのでインターフェイスが必要だったのではないかと考えています。逆に、多重継承があれば、インターフェイスは要らなかったのではと考えています。

コンセントの例でしたら、抽象クラスでも同じことが出来るわけですし。なぜ、Javaに多重継承がないのかが疑問です。

投稿

tf2014

tf2014

score 48

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • tsunex

    tsunex

    2017/03/28 14:37

    自分はこんなイメージで認識してます。

    抽象クラス
     家電とコンセント
     家電にはいろんなものがありますがコンセントは基本同一
    インターフェース
     ネジと多機能ドライバー
     ドライバーの先端はねじにあったものに交換

    キャンセル

  • xenbeat

    xenbeat

    2017/03/28 15:15 編集

    >Jave,C#は多重継承がないのでインターフェイスが必要
    C#はわからないですが、Javeに限っては違うと思います。
    >なぜ、Javaに多重継承がないのかが疑問です。
    「James Arthur Gosling」が、多重継承の複雑な問題、多重継承があってもほとんど使用されないという理由から機能を省略したと、JavaのOverviewで明言しています。
    http://www.cs.dartmouth.edu/~mckeeman/cs118/references/OriginalJavaWhitepaper.pdf
    Javaにおいて、多重継承の機能を省略することは欠陥ではなく、実装者にとっては良いことだと考えます。

    キャンセル

  • akabee

    akabee

    2017/03/28 15:48 編集

    私も議論に参加したくなりました。

    抽象クラスはインターフェースより自由度が高いイメージですね。
    家電製品とコンセントの例で抽象クラスを引き合いに出すのであれば、一つの家電製品を作るときに抽象クラス「家電製品」を継承しその中の抽象メソッドの一つに「コンセント」があるか、インターフェース「コンセント」を継承するかの違いと言えるのではないかと思います。
    インターフェースのほうが制約が大きいのですが、プログラミングの世界では制約が大きいことによるメリットも大きいですから、要は使い分けだと思います。

    Javaに多重継承がない点についてですが、オブジェクト志向的にも多重継承は微妙なんですよね。。「多重継承を使いたい」というような状況は、残念ながら、クラス分けがしっかりできていない状況に該当していると思います。Javaに多重継承が無いということと関連があるかないかは分からないのですが。

    家電製品の例を引っ張って申し訳ありませんが、例えば勉強机とかこたつとか、家具と分類されるようなものにもコンセントがある場合がありますよね。
    そういう場合にクラス「家具」と「家電製品」を多重継承するのは、なんだか家具に必要ない家電製品の機能までたくさんついてきそうじゃないですか?
    であれば、コンセントが必要な家具であれば抽象クラス「家具」を継承した上でインターフェイス「コンセント」も必要であれば実装すればいい。勉強机には電気を付けられるものもありますから、コンセントの他にも追加で「電気取り付け具」や「電気のスイッチ」も付加すればいい。そういう実装であればJavaも認めています。

    私は上記のような理解をしています。

    キャンセル

  • tknakamuri

    tknakamuri

    2017/03/28 23:45

    今のJavaは制限付きで多重継承できますよ。
    Java8からです。

    キャンセル

  • tf2014

    tf2014

    2017/03/29 13:12

    Original Java Whitepaper を流し読みしてみました。 2ページに確かに「よく理解されていない、タメにならずダメになるC++の機能は削除した。」と書いてあります。
    多重継承がないことが良いことという決断に基づきJavaを製作を進めてたら、困ることに気づいた。そこで、インターフェイスというキーワードを作った…とは考えられないでしょうか? 以上は、ロバート・マーチンの講習での話しに基づく私の推測ですが、マーチン自身ブログで「インターフェイスの存在はJava製作者の怠惰だと推測する」と書いています。
    http://blog.cleancoder.com/uncle-bob/2015/01/08/InterfaceConsideredHarmful.html

    更に、マーチンは言語の製作者は開発者を 多重継承できないと制約することでなく、多重継承するかどうかは開発者の自由であるべきで、開発者が責任を持つべきだといった内容を話していました。

    以下の抽象クラスは、多重継承が出来ないことを除いてはインターフェイスとまったく同じことを達成できます。

    public abstract class Consent{
    public abstract void SupplyPower();
    }

    abstractキーワードがあるのでSupplyPower関数はオーバーライドされなくてはならない。つまり、インターフェイスで定義されたメソッドは定義されなくてはならないことと同意。

    public interface Consent{
    public void SupplyPower();
    }

    ...と書きましたが、私自身インターフェイスは多用するし、依存性の注入でも、抽象クラスでなく、インターフェイスを注入します。理由は、コーディング・スタンダードがインターフェイスという機能があることに基づいて進化した、他の開発者と同じスタイルを取り、読みやすいコードを目指すこと、Akebeeさんが書いたように「インターフェースのほうが制約が大きいのですが、プログラミングの世界では制約が大きいことによるメリットも大きいですから、要は使い分けだと思います。」に合意するからです。

    ちなみに、コンセント(ソケットの形状を複数の電力会社で「合意」して決めた consent plug)はインターフェイス=「継承したメソッドを定義するという契約」に合意するという例としよく分かりやすいものだと思います。

    キャンセル

  • MasahikoFukui

    MasahikoFukui

    2017/03/29 17:41 編集

    多重継承が複雑な問題を(主に型変換で)引き起こすのは周知に事実として、
    実例はみなさん書いているおられるようなので、ちょっと余談を...

    昔のオブジェクト指向フレームワークって継承だけで全てを構築しようという姿勢で作られていたんですよ。多重継承でなんでも取り込むみたいな。

    それから90年代中頃になると、それらのフレームワークもデリゲーションモデルを取り入れるようになって、実装とインタフェースのクラスを分けて作るようになるわけです。インタフェースがないので結局は多重継承なんですが(^^;)

    ちなみにJavaのフレームワークにもそういった継承万能主義の名残がありますよね。
    コンポーネントにマウス操作のハンドラが残ってたりとか。あの頃は仕様を見ただけで実用に耐えないフレームワークだと思っていたけど、程なくイベントリスナ(インタフェース)を使ったイベントメカニズムが登場しました。

    そんなわけで、なぜインタフェースで十分かを知るにはデリゲーション(移譲)モデルを理解すると良いでしょう。実感できますよ。

    結局、デリゲーションモデルを使うと、継承するのはそのクラスの本質的な機能を持つ御先祖様だけで、それ以外の機能の口はインタフェースを継承して、処理方法を知っている他のクラスのインスタンスを作って右から左に流してやる感じで間に合っちゃうんですよ。

    キャンセル

+2

小規模の開発であればインターフェースを実装するメリットはあまりありません。
インターフェースを利用するメリットはメンテナンス性の向上だと思います。

インターフェースは実装されるクラスによって実装方法は異なりますが、インターフェースを実装されたクラスではそのメソッドを見れば何の目的のメソッドなのかわかります。

インターフェース:泳ぐ
インターフェース:飛ぶ
インターフェース:走る

基底クラス:動物(食べる、寝る、遊ぶ)

子クラス1:哺乳類

孫クラス:ジャガー←インターフェース:泳ぐ、走る

基底クラス:動物

子クラス2:カラス←インターフェース:飛ぶ

投稿

php5

php5

score 10

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

ざっくりと説明すると、サービスを提供する側(ライブラリーなんかがそうですね)が、

「うちのサービスを使うときには、この『資格』を満たしてね!」

ということを、あらかじめ決めておくための仕組み、
って感じですかね。

資格を満たす=規定されたメソッドを実装する。

ですね。

同じようなことは、もちろん、クラスの派生でもできるんですが、
インターフェースのほうが、使いやすい場面があるということなんですね。

ちょっと、例え話での説明に挑戦してみます。

すべての動物が参加できる、オリンピックが開催されるとします。
それをシステムとして考えてみましょう。
(なんて例えだw)

オリンピックなんで、幾つもの競技があります。
100m走、水泳なんかは、人間界にもありますが、
全動物ですから、飛行競技だってあったりします。

100m走に出場するため『資格』は、「走れる」ことで、
(走る)という行動が取れることです。
水泳に出場するための『資格』は、「泳げる」ことで、
(泳ぐ)という行動が取れることです。
飛行競技に出場するための『資格』は、「飛べる」ことで、
(飛ぶ)という行動が取れることです。

オリンピック運営側(サービスを提供する側)は、
各競技ごとに必要な『資格』をあらかじめ決めておくことで、
どんな動物が出場できるかを提示することができますよね。

さて、次は、参加動物(サービスを利用する側)について。

それぞれの競技に参加できるのは「どんな動物か?」
「走れる」動物、「泳げる」動物、「飛べる」動物です。

鳥や、魚や、四足歩行、二足歩行、なんかで分類しようとすると、
ちょっと無理がありますよね。

例えば・・・

魚であるトビウオは、水泳に参加できる。
魚であるトビウオは、飛行競技にも参加できる。(ちょっと違うくない?w)
鳥であるワシは、飛行競技に参加できる。
ペンギンやダチョウは、鳥なのに、飛行競技に参加できない。(なんてこった)
四足歩行のチーターは、100m走に参加できる。
二足歩行のヒトも、100m走に参加できる。
鳥であるダチョウは、100m走には参加できる。(おお!)
鳥であるペンギンは、100m走には参加できる。(参加することに意義あり!)
鳥であるペンギンは、水泳にも参加できる(おお!!)

さあ、鳥はどうやって分類(汎用クラス)しましょう?
飛べる鳥、
飛べない鳥、
飛べないけど泳げる鳥、
飛べないけど走れる鳥、
飛べないけど走れて泳げるペンギン(笑)

もう、抽象化の意味がなくなってきそうですw

そこで、『資格』(インターフェース)ですね。
『資格』を特徴として考えて、

鳥「飛べる」
鳥「走れる」
鳥「走れる」「泳げる」

というように、より抽象的な鳥クラスを、それぞれの『資格』(インターフェース)で補足するほうが、
表現しやすそうです。

ペンギンは、鳥で、「走れる」「泳げる」『資格』を実装しているわけです。

さて、話をオリンピック運営側に戻します。

上記のように、それぞれの動物が、競技ごとに必要な『資格』(インターフェース)を実装しているわけですから、

100m走に参加する動物は、(走る)という行動がとれることが保障されています。
同じように、水泳や飛行競技に参加する動物も、(泳ぐ)、(飛ぶ)という行動が取れます。

ですので、オリンピック運営側は、参加動物に対して、(走れ)と号令をかけるだけで、100m走の競技を開始することができるわけです。

以上、自分の少ない知識を総動員させて、書いてみましたがいかがでしょうか?

きっと、インターフェースにはもっと高尚な効能がたくさんあるはずなのですが(正直、私のレベルではわかりませんw)、取り掛かりとしては、こんな感じがイメージしやすいように思います。

以前は、コードを重複させないよう、クラスの汎化にこだわりたくなってました。が、現実、設計に時間がかかりすぎることが多かったです(笑)そして、汎化した意味があまりなかった・・・なんてことも(笑)

クラスの汎化は、コード重複を減らすため、よりは、問題領域の概念を正しく表すこと、のほうが大事ですよね。

実装が多少散らばっても、早く動くものを作りながら、リファクタリングをしつつ、見えてきたものから抽象化していく、という流れが、現実的なのかな?と考えてます。

投稿

Meganezaru

Meganezaru

score 470

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

上位層に変更がなく、機能を変更するために必要です。関数でなく、クラスとして機能を定義するものです。インターフェースで、下位層の機能を定義できれば、上位、下位が同時並行に開発可能になります。

投稿

suna9123

suna9123

score 2

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

>最初からきちんと完璧に設計すれば早いと思うのですがどうでしょうか

まさに書いているじゃないですか?
しっかりと設計をする。
設計をしっかり守らせる。
守らせる為の制約手段ですよ。
多人数になると制約が必要になってくるものです。
メソッドのスペルミスなどもコードチェックの段階で回避できます。

投稿

編集

youcova

youcova

score 8

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

疎結合 というのが的確な答えなんですが、プログラムの
規模が大きくなると、インターフェースによる疎結合は
不可欠なものです。プログラムがモノリシックで複雑な化物に
なることを防ぐ有用な武器です。

オブジェクト指向である程度規模の大きなプログラムを組むにあたって
必要とされる基本原則の一つに、
IOC(Inversion of Control)
があります。多くのオブジェクト指向設計の本で詳細な
具体例が解説されていますで、それらを読むことをおすすめします。

投稿

tknakamuri

tknakamuri

score 28

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

すでに接点としての回答が出揃っているので、別の観点での補足みたいな感じです。

javaで解説すると、インターフェースは質問者がおっしゃっている、「設計」です。
設計をきちんとするということは、インターフェースをきちんと作るということです。

インターフェースはインプリメンツしますが、インプリメンツには、
条例を施行する、規約を実施する、という意味があります。
クラスは実装ですから、インターフェースは設計、となります。

なので、設計がブレれば、実装もブレます。
完璧に設計できれば、実装も完璧かと思います。

オブジェクト指向言語は、
言語としての機能としてこれらを備えている、というところでしょうか。

投稿

編集

YSMS

YSMS

score 16

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • オブジェクト指向

    286questions

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

  • オブジェクト

    92questions

    オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

SNSアカウントでログイン

  • Facebookでログイン
  • Twitterでログイン
  • Googleでログイン
  • Githubでログイン
  • Hatenaでログイン

teratailアカウントでログイン

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る