2012-02-29 3 views
25

JavaやC#などの言語でPure Abstractベースクラスを使用する理由がないと主張していた同僚と議論していました。多重継承の欠如を回避することはできません。Pure Abstractクラスとインターフェイスの違い

私は常に物事が名詞であればそれはオブジェクトであり、動詞であればそれはインターフェースであると常に考えていたので、彼はこれについて間違っていると感じます。

例えば、Birdという型を定義したければ、実装しないでflyというメソッドを適用したい場合は、純粋な抽象クラスにします。

タイプFliesを定義したければ、メソッドflyとのインタフェースにします。

BirdFliesを実装しています。

私は間違っていますか?

編集:私は私の視点をサポートするために与えることができます

だけ固体の引数は将来のある時点で、デザインは鳥が食べることができるように変更する必要があるかもしれないということです。すべての鳥が同じものを食べたら、Birdに追加する必要があります。

Birdがインタフェースであった場合、他の基本クラスから継承するものも私のBirdインタフェースを実装しているかどうかわからないため、この変更は単に悪夢となります。

+0

+1 - 良い質問と私は、抽象クラスの使用のために来る答えには多くの合理的な理由が検討されると思います。 –

+3

あなたの質問の*部分*を拾うだけです(したがって、*回答*を投稿しません):私はそのインターフェースが常に*動詞*であるとは言いません。インターフェースは、*クラス*を使用して、クラスが名詞として最もよくモデリングされた顔を世界に示すことを可能にします。 'java.util'のインタフェースのいくつかを見てみましょう:' Comparator'、 'Enumeration'、' List'、 'Iterator'、' Map'、... –

+1

意見は背中のようなものです。他より。私はOOPと文法を比較するのは間違いだと思いますが、それは近いです。 – Lloyd

答えて

6

あなたの最初の編集は別として、将来の要件です。可能なユースケースの1つは、定数を宣言して抽象クラスで初期化することができます。

import java.util.ArrayList; 
import java.util.List; 


public abstract class AbstractPure implements ISomeInterface { 
    public static final List<String> days = new ArrayList<String>(); 
    static{ 
     days.add("Monday"); 
     days.add("Tuesday"); 
     days.add("Wednesday");  
     days.add("Thursday"); 
     days.add("Friday"); 
     days.add("Saturday"); 
     days.add("Sunday"); 
    } 
} 
+1

非常に良い点! – sji

+6

技術的にはそれはもはや純粋な抽象クラスではありません... – zmbq

+1

個人的に私は、インタフェースの定数は多くの場合、設計上の問題であると思います - 少なくとも、プリミティブと列挙型では処理できないすべてのものです。しかし、それはインターフェイスでは不可能な有効なポイントです。 – Voo

1

純粋な抽象クラス(私は最後にC++を使用してからしばらくしています)で検索しましたが、私が見つけることができる唯一のケースはC++(インターフェイスを持たない)でインターフェイスを定義することでした。

純粋な抽象クラスを使用できるとすれば、あなたの友人が言ったように、インタフェースを使うこともできます。

しかし、私はC#で純粋な抽象クラスの必要性に遭遇したことはないので、これは仮説的な問題かもしれません。

+0

私はこれについての私の考えに影響を与える可能性のあるC++のバックグラウンドから来ているのですが、やはり抽象基本クラスの潜在的な必要性を示すために質問を拡張しました。 – sji

+1

はい、突然どのインターフェースが突然食べられるのかはどうですか? – zmbq

0

私は、インターフェイスとクラスの両方がオブジェクトを定義していると言います。あなた自身が言ったように、動詞はメソッドに行きます - それらはこれらのオブジェクトのプロパティです。あなたのフライの例では、私はインターフェイスFlyingCreatureを宣言し、そこにメソッドフライを定義します(したがって、ComparableSerializableのようなインターフェイスはSerializeCompareではありません)。方法はcompareToです。また、あなたの他の例について - 鳥:あなたは鳥のためのロジックを持っていない場合は、それはインターフェイスとして宣言します。

インターフェイスは、異なるタイプのオブジェクトに共通のプロパティを宣言するために使用され、それらを分類的にグループ化します。後で、あなたが同じインタフェースを持っていることを知っているという事実を利用して、それらを同じ方法で処理することができます。

抽象クラスとインターフェイスの両方がオブジェクトを宣言していると私はすでに述べているので、純抽象クラスでは何の利得も見られません。

+0

私は鳥をインターフェイスにする潜在的な欠点を指摘するために質問を広げました。 – sji

10

私は、少なくとも一つの良い理由を考えることができます:あなたは、後方互換性を壊すことなく、後に抽象クラスを拡張することができます:我々はインタフェースを使用している場合は、私たちが今いることを確実に知る

abstract class/interface Foo { 
    void foo(); 
} 

クラス/インタフェースを想定Fooに追加機能を追加する方法はありません。これはinterface Foo2 implements Fooのようなものにつながります。

一方、抽象クラスを使用している場合は、基本実装を提供している限り、別のメソッドを簡単に追加できます。

Java8では、インタフェースが基本的に同じことを行うことができます。これは、ラムダを使用してライブラリを更新して、既に書かれた何百万行ものコードとの互換性を必ずしも失わずに済みます。

+0

これも私が考えることができる唯一の理由です。引数の反対側を取る:何かが実装された追加の機能を必要としないことをいつどのように知っていますか?何かが間違いなくインターフェースなのでしょうか?私は恐怖のためにインターフェイスを使用しないでください。 – sji

+0

@sji最終的には、実際のビジネスケースに依存する判断のコールです。明らかなこととは別に、私はそこに一般的に役立つことはあまりありません。少なくともJavaでは、多重継承はないという事実もあります。 Java8では、インタフェースをデフォルトの実装にすることで、これをもっと明確にするための長い道のりが必要になります。 – Voo

0

別のインターフェイスを実装する複数のプラグインタイプを使用するプラグインシステムがあるとします。

リフレクションを使用して、これらのプラグインクラスを実行時に見つけることもできます。

これはインターフェイスなので、1つのプラグインは複数の種類のプラグインにすることができます。

各プラグインタイプを抽象クラスにすると、継承階層が制御され、各プラグインが個別のタイプであることが保証されます。

純粋な抽象クラスとインタフェースの間には違いがあります。これはあなたが使う必要があるものではありませんが、どちらも++、再帰、またはオブジェクトさえありません。

0

私はこれに関連するものではありませんでした。基本的には、アイテムがリンクされている場合は、抽象クラスを使用します。それが何かのプロパティを記述している場合は、インタフェースを使用します。

あなたの例を使用すると、同じ場所からワシやオウムを派生させたいので、鳥は抽象クラスになります。

「フライヤー」のようなものがほしいと思ったら、鳥や飛行機などがインターフェイスを実装している可能性があるため、インターフェイスを作成します。

もうひとつ考慮すべきことは、ある時点で、実際にあなたの鳥のためのいくつかの具体的な方法を入れたいということです。結局のところ、すべての鳥が同じように飛ぶので、鳥が飛ぶたびに、「フラップフラップフラップ」を印刷することをお勧めします。インターフェイスを使用している場合は、各クラスでそれを行う必要があります(または新しい基本クラスを導入する必要があります)。一方、抽象クラスを最初に使用した場合は、その動作を1つの場所に追加するだけです。

関連する問題