2016-07-13 3 views
0

インターフェイスを定義し、基本抽象クラスでインターフェイスを実装し、既定の動作を与えてから基本クラスから継承することをお勧めしますか?インターフェイスと基本抽象クラスc#

それはあまりにも重いですか?

+0

あなたが達成しようとしていることに依存します...インターフェースは、あなたのコードをすべて変更することなく実装を変更できるように、契約を中継する機能を提供します。基本クラスは、デフォルトの動作を記述するのに便利です。 – Thomas

答えて

4

インターフェイスまたは抽象クラスのどちらを使用するかは、全く異なる2つの質問です。両方の答えがyesですが、一方はもう一方とは関係ありません。

基本クラスを継承し、特定のメソッドを共有する複数のクラスが必要であることが絶対に確実でない限り、継承を使用するように前もって計画しません。完璧な教科書のクラス階層を考え始めると、しばしば複雑になり、うまくいきません。あなたがリファクタリングをしているときや、同じようなクラスを作成してコードを複製したくないと思うときは、しばしば意味をなさないでしょう。

インターフェイスを作成して実装することは、別のクラスが依存する(非常に多い)ものを作成するときには良い習慣です。たとえば、クラスが依存することがわかっている場合「何か」を行う別のクラスでは、最初のクラスで作業を一時的に中断してIDoesSomethingインターフェイスを作成し、IDoesSomethingに依存する最初のクラスを終了することができます。あなたは実装がまだ何かを理解していませんが、あなたがすでに書いているクラスはインターフェイスに依存しているので問題はありません。 (Inversion of Control - 良い練習。)次に、IDoesSomethingを実装するクラスを書くことができます。

例をあげて説明します。

public class MenuProvider 
{ 
    public Menu GetMenu(string menuId) 
    { 
     //code that gets the menu 
     return menu; 
    } 
} 

その後、私は、私はそれを返す前に、特定のメニュー項目をフィルタリングする必要がありますするつもりだことを実現:私はMenuItemオブジェクトのネストされたリストが含まれているMenuオブジェクトを提供するクラスを書いているとします。これは、構成設定、特定のユーザー、または何か他のものに基づいている可能性があります。

私はこのインタフェースを書くかもしれません:

public interface IMenuFilter 
{ 
    void FilterMenu(Menu menu); 
} 

し、このように私の元のクラスを変更します。

public class MenuProvider 
{ 
    private readonly IMenuFilter _menuFilter; 

    public MenuProvider(IMenuFilter menuFilter) 
    { 
     _menuFilter = menuFilter; 
    } 

    public Menu GetMenu(string menuId) 
    { 
     //code that gets the menu 

     //filter the menu 
     _menuFilter.FilterMenu(menu); 
     return menu; 
    } 
} 

私はIMenuFilterの実装があることを行っているのか分かりません。実際には、それぞれが1つのタイプのフィルタリングを実行する一連の別々のクラスの複合体になる可能性があります。しかし、ポイントは、私はそれを把握するために私が行っていることを停止する必要はありません。私はこのクラスを書くことができ、嘲笑してIMenuFilterでテストしてから、そのフィルタの詳細を書くことができます。

+0

返信いただきありがとうございます! – MaitlandMarshall

2

このインターフェイスの実装で共有する共通の機能はありますか?その場合は、抽象基本クラスを作成します。さもなければ、それについて今心配しないでください。後でいつでも追加することができます。しかし、インターフェイスへのプログラミングは、ほとんどの場合、常に良いアイデアです。

1

通常、のいずれかのインターフェイスまたは継承を使用します。私は通常、同じクラスでは両方を使用しません。

基本クラスから機能を継承する場合は、継承を使用します。

異なるクラスに同じコア機能を実装したいが、コードを共有する必要はない場合は、インターフェイスを使用します。

+2

私は個人的にこれに同意しません。十分に複雑なシナリオでは、具体的な実装をDRYに保つために抽象基本クラスの階層を維持しながら、インターフェースに対してコンシューマーコードを記述するのは完全に合理的だと思います。 –

+0

実際の例:ソフトウェアは、 'IOutputController'の非抽象実装のためにリフレクションを使用してプラグインアセンブリをクエリします。プラグイン(メインアプリケーション以外の誰かによって書かれたもの)は、このインタフェースを実装します。メインアプリケーションから提供される 'OutputControllerBase'、' SerialOutputControllerBase'、 'ParallelOutputControllerBase'のような様々なABCから継承することができます。しかし、彼らは 'IOutputController'を実装するだけで済むので、それらのどれからも自由に継承することができます。 –

+1

私もこれに同意しません。抽象クラスのインターフェイスを通常は使用しないことを提案するには、他のクラスと何か関係があることを示唆します。インタフェースは実装と実装を切り離します。なぜ、抽象クラスを含む実装が*唯一の実装であると期待するのでしょうか?同じように、複数の実装を持つインタフェースを持つことがよくありますが、抽象クラスを含むものもあります。また、インタフェースはクラスの機能を共有することとは何の関係もありません。共通の機能を持たない実装を持つことが可能になります。 –

関連する問題