• ベストアンサー

インターフェースとサブクラスはどっちを使えばいい?

ある機能Aを持ったクラスを作りたいとき、次の二つの方法があると思います。 (1) サブクラス → 機能Aを持ったクラスを拡張したサブクラスを作る。 (2) インターフェース → 機能Aを実現するメソッドをまとめてインターフェースにし、そのインターフェースを実装するクラスを作る。 これらの使い分けはどうすればよいのでしょうか?つまり、どういうときに(1)を使ってどういうときに(2)を使えばよいのでしょうか? 私が現在思いつく(1)と(2)の違いは以下の二つです。 ・(1)の方法は手軽 ・(1)の方法だと、一つのクラスの拡張しかできない これくらいでしょうか。もっと本質的な違いはあるのでしょうか?

  • Java
  • 回答数6
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.3

基本はインタフェースです。 インタフェースがあれば、拡張によることはすべてできます。 extendsによる拡張は、Java言語に別に無くてもいいけれど、 プログラマの便利のために存在しているものです。 オブジェクト指向のえらい人ピーター・コードは、 継承を使うときの基準として以下のような条件を挙げています。(『Peter CoadによるJavaオブジェクト設計』) (1)「何々の特別な種類」であって、「何々によって果たされる役割」ではない (2)(継承を使ったときに得られるオブジェクトは)何か別のクラスのオブジェクトに変形する必要は生じない。 (3)スーパークラスを拡張するのであって、スーパークラスをオーバライドまたは無効化するのではない。 (4)ユーティリティクラス(プログラム上の便利のためのクラス)に過ぎないクラスをサブクラス化するのではない。 (5)PD(問題領域:実現しようとするシステムの中で本質的なもの)の中では、役割、トランザクションまたはデバイスの特別な種類を表す。 要するに、 「Aを拡張したBは、絶対にあくまでもAに属する一種類である」 と確定していない限り、継承は使うなということです。 機能だけを使いたいなら、継承でもインタフェースでもなく、 コンポジションというやり方もあります。(上記の参考文献参照) ポリモーフィズムを使う必要がない場合は、 この方法が安全確実ではないかと思います。

参考URL:
http://www.amazon.co.jp/exec/obidos/ASIN/4894710145/
white-tiger
質問者

補足

ありがとうございます! これは良さそうな本ですね。購入しようと思います。 翻訳は読みやすいでしょうか? 読みにくければ原書を買おうと思います。

その他の回答 (5)

  • aton
  • ベストアンサー率47% (160/334)
回答No.6

既に他の方がいろいろ書かれているので,私は少し別の視点から。 サブクラスとインターフェイスの違いは,実装の集中管理をするか否かにあるのではないかと思います。 サブクラスを利用している場合,親クラスのあるメソッドの実装が変更されたとすると,それは(子クラスでオーバーライドしていない)全ての子クラスのメソッドにも自動的に反映されます。 一方,これがインターフェイスの場合,親クラスの実装の変更は子クラスに及ばないので,もし同様に変更を反映させたい場合,全ての子クラスの実装を(コピペかなにかで)同様に変更してやる必要があります。 もちろんこれは良し悪しで,親クラスの実装の変更が自動的に子クラスに反映されることで,予期せぬ変更が生じて困る場合もあります。 以上から,個人的には, ・作り始めの段階ではサブクラスで継承を使って実装を一元管理する ・デバッグが進んで,それ以上実装が変更されることがほとんどないと考えられる状態になったら,インターフェイスに置き換える(ただし,他の方が書かれているように,サブクラスにする必然性のあるものまでインターフェイスに置き換える必要はありません) というのがいいのではないかと思います。 #これはNo.2の方がいわれている方法とよく似ていますね。

white-tiger
質問者

補足

実践的なアドバイスをありがとうございます。 インターフェースが基本だ、と思いつつあったので、 >サブクラスにする必然性のあるものまで >インターフェイスに置き換える必要はありません これは勘違いしていました。

  • sasadora
  • ベストアンサー率68% (59/86)
回答No.5

オブジェクト指向が流行りだした以前は、 「オブジェクト指向」といったら、「継承」というくらいよく聞かれたのですが、その弊害についても色々と議論され、近年では継承の危険性についてよく聞きます。 http://www.pc-view.net/Solution/040120/page14.html No.3の方のおっしゃるように、インターフェースでできないかをまず検討すべきだと思います。 継承する(サブクラスを作る)にしても、よく検討しないと危険なので、むやみやたらに使うべきではないということです。 Effective Javaは誰もが認める良書だと思います。 第四章 クラスとインターフェース  14 継承よりもコンポジションを選ぶ  15 継承のために設計および文書化する、でなければ継承を禁止する  16 抽象クラスよりインターフェースを選ぶ

参考URL:
http://www.amazon.co.jp/exec/obidos/ASIN/4894714361/
white-tiger
質問者

補足

私は C++ 出身なのですが、たしかに、継承で悩むことが非常に多かったです。 Effective Java、読んでみます。ありがとうございます。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

>ということは、サブクラスで実現できるときはサブクラスで、ということでしょうか? #3の方針がいいっすね。 私も、機能(クラス)の特殊化・機能拡張がサブクラスというようなことでいいと思います。 多重継承したくなるような時というのは、機能(クラス)が他にも欲しいときというような感じでいいんじゃないですか

  • unibon
  • ベストアンサー率47% (160/340)
回答No.2

これは深い問題であり、人それぞれの考えがあると思います。以下は、私の経験で得た考えです。かなり異端だと思いますが、ご参考までに。 インターフェースはそれ自体は状態(フィールド)を持たない代わりに、後からいくらでもどんなクラスにでも付け足すことができるものです。一方、クラスは状態を持つことができるのですが、後から付け足すことができないものです。 インターフェースは、十徳ナイフを作るのには便利で臨機応変が効きます。クラスはツブシが効かないですが、本来は状態と密に連携できるクラスで作ることを考えて作ったほうがキレイな設計になることが多いと感じます。ただ、動的な設計変更が起こり得るようなことを考慮すると、本当はクラスのほうがいいんだけど、インターフェースでもできるからインターフェースでやっちゃおうか、という考え方で割り切ったほうがいろいろとメリットが出てくるかもしれません。 したがって、設計は abstract class を基本にし、それを extends した (concrete な) class を作ることを念頭に置いて、しかしコーディング時はそれを interface に置き換えてしまうほうがいいのではないかと考えます。

white-tiger
質問者

補足

> 設計は abstract class を基本にし、それを > extends した (concrete な) class を作ること > を念頭に置いて、しかしコーディング時はそれを > interface に置き換えてしまう ありがとうございます。 ちょっと完全に理解できていないのですが、出来るだけインターフェースにしておいた方がよい、ということでしょうか?

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

ありきたりの回答ですが、 サブクラスによって実現できないような場合(多重継承みたいな感じになる時)インターフェースを使うというのでどうでしょう

white-tiger
質問者

補足

ということは、サブクラスで実現できるときはサブクラスで、ということでしょうか?

関連するQ&A

  • 抽象クラスとインターフェースの使い分け

    抽象クラスとインターフェース、この2つの違い、使い分け方が未だにはっきりとはわかりません・・・ 抽象クラスもインターフェースも実装は持たず、抽象クラスはサブクラスで、インターフェースはそれをインプリメントしたクラスで実装を行うのですよね? 両者ともに言わば中身はなく外枠だけ定義されていると言えると思うのですが、だとしたらこの2つの違いや使い分けってどうなるのでしょうか。 抽象クラスでは部分的な実装を含められることや、インターフェースでは実装クラスが全てのメソッドを実装しなければいけない、複数実装できるといった使い方の違いしかないのでしょうか。 だとしたら実際に抽象クラスとして用意するのかインターフェースとして用意するのかの選択基準はなんなのでしょうか。 明確にこういう場合は抽象クラス、こういう場合はインターフェースなどと言った使い分けってあるのでしょうか。

  • インターフェース

    インターフェースについて学ぼうと思っているのですが、 どうもいまいち何がなんだかわからなくなっています。 インターフェースはクラスによって実装され、 実装クラスはインターフェースで宣言されている 抽象メソッドを実行する とあるのですが、実装とは何ですか? 抽象メソッドとは何ですか?

    • ベストアンサー
    • Java
  • アブストラクトとインターフェースの簡単な一例文

    JAVAについて質問よろしくお願いします。 abstract抽象クラスとインターフェースについて下記理解なのですが、超かんたんな一例など欲しいのですが何かないでしょうか。たとえば package round1.chapter1; public class Helloworld { public static void main(String[] args) { System.out.println("こんにちは!"); } } というような一文です。 ~私の理解~ アブストラクトとは、違ったクラス内で同一メソッドがある場合は親クラスに置き、違ったメソッドがある場合は抽象クラスとして親クラスに置いて、実装はサブクラスに任せるという形式で使われる言葉 インターフェースとは、機能だけを仕様書として書いておき、定義されたとおりのメソッドを実装しないといけないという呼び出し方の統一を図る際に使われるメソッド置き場 ~~~~~ このふたつについてものすごく簡単な使用例を頂きたいです。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • スーパークラスのインスタンスをサブクラスにアップキャスト

    ↑したい場合はどうしたらいいでしょうか。 データ構造体(beans)なのでスーパークラスのgetterとsetterを 利用してサブクラスに再構築する方法が考えられますが どうも腑に落ちないので質問してみました。 サブクラス側で継承をやめて集約にするにしても getterとsetterをまた書くの?って感じでわずらわしいです。 (jsp:getPropertyを利用するかもしれませんしね) さらにスーパークラスのメソッド全てをインタフェース化してサブクラスで実装とかしてたら具合が悪くなってきます。 この長年の疑問に終止符を打ってくれる方はいませんか?

    • ベストアンサー
    • Java
  • interface,extend,implementのちがい

    お世話になります、 Javaを勉強しているのですが、 interface,extend,implementの使い分けがわかりません。 私の解釈としては、 (1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。 (2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。 (3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか? とにかくこの3つのを使い分けるコツとかあれば教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 「インタフェースを実装してそれが持つ抽象メソッドをオーバーライドする」

    「インタフェースを実装してそれが持つ抽象メソッドをオーバーライドする」は正しい? はじめまして。Javaのインタフェースに関する質問です。 私はこれまで、インタフェースを使うときは、インタフェースを実装してクラスを宣言し、そのクラス、またはサブクラスでインタフェースがもつすべての抽象メソッドを定義する、と理解していました。 しかし、下の例をみてください。抽象メソッドの定義を、インタフェースの実装の以前で与えています。問題無くコンパイルでき、実行できます。実行結果も以下の通りです。 インタフェースの抽象メソッドへの定義の与え方やその実行のされ方は、メソッドのオーバーライドと同様と思っていましたので、下記のコードでは「クラスBが抽象クラスではありません」や、「インタフェースの抽象メソッドがオーバーライドされていません」などの文法エラーがでると思っていました。 そこで、質問です。 インタフェースが持つ抽象メソッドの定義を与える場所について、または、これに関する説明のあるページなど、何かご存知でしたら教えてください。 ★コード★ interface X{   void show(); } class A{   public void show(){     System.out.println("A");   } } class B extends A implements X{ } public class Main{   public static void main(String[] args){     X x=new B();     x.show();   } } ★実行結果★ >java Main A ★Java環境★ java 1.6.0_21 javac 1.6.0_16

    • ベストアンサー
    • Java
  • サブクラス型オブジェクトをスーパークラス方に代入

    ある所で下記のような継承についての記述をみつけました。 ----------------------------------------------------------------------------- 継承の目的は、あるクラスで実装したメソッドなどの機能を利用して、 さらに実装を追加する差分コーディングです。 一つのクラスから複数のサブクラスを作ることも良くあります。 このような時、それらのサブクラス型オブジェクトの参照を代入できる変数として、 スーパークラス型変数を使うことがしばしばあります。 ----------------------------------------------------------------------------- サブクラス型オブジェクトの参照を代入できる変数として、 スーパークラス型変数を使うことがある、と いうのはどういった場合に使うのでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Java
  • RubyでJavaのInterfaceに相当するものはありますか?

    RubyでJavaのInterfaceに相当するものはありますか? Ruby 上で Javaの interface のようなものものを実現するには、どうしたらよ いのでしょうか? Rubyは型を宣言しないので機能的には interface は不要ですが。 クラスを実装する人に、あるクラスに実装しなければいけないメソッドを伝える (強制する)目的としての interface 的な使い方をしたいのです。 宜しくお願いいたします。

  • フレームワークによくあるインターフェースについて

    たとえばSpringだとInitializingBeanインターフェースを 実装してafterPropertiesSetメソッドに処理を書くことによって Beanを初期化したときにその処理が実行されるようですが、 これはどのような仕組みでそのインターフェースを実装しているか どうかを判断しているのでしょうか? getInterfacesメソッドを使うとそのクラスが実装している インターフェースを調べることができるようですが、 これは親クラスのインターフェースまでは調べられないようですし、 フレームワークはどのようにしてそのクラスが実装している インターフェイスを判定しているのか不思議です。

    • ベストアンサー
    • Java
  • interfaceを実装するとは?

    interfaceを実装するとはどういうことですか? abstractはクラスの継承で 学校 -abstract(拡張)― 教室 ―abstract(拡張)― 生徒 と機能を細分化するものとわかりました。 インターフェースってなんですか・・

専門家に質問してみよう