2009-11-06 22 views
45

私はこれについての答えを見つけることができないと思うだけで、それはOK標準をコーディングしていることを確認したい。私は多くの異なるクラスで使用されているインターフェースAを持っていて、インターフェースAを変更したくないのです。私はインタフェースAを実装するクラスの多くが必要とする列挙型を必要とする新しい要件を見つけましたが、すべてのクラスがこの列挙型を必要とするわけではありません。私はこの新しいenumを必要としないクラスがこの新しい機能を実装することを望んでいません。そこで追加する必要があった新しい列挙型を含むインターフェイスBを作成しました。私は次にInterface B Inherit Interface Aを作成しました。これは私の心配です。あるインターフェースが別のインターフェースを継承しても大丈夫ですか?変更を続行するには、インタフェースBで継承されていたので、インタフェースAの代わりにインタフェースBを実装する必要があるクラスを変更しました。両方のインタフェースを必要とするクラスに実装することを考えましたが、コード全体のインターフェイスで、2つではなくクラスを調べるために1つのインターフェイスを使用したいと考えています。1つのインターフェイスが別のインターフェイスを継承する必要があります

私はこれが十分に長い(おそらく長い)ことを望みますが、誰かが私にこれについていくつかアドバイスを与えることができれば、私はそれを正しくやっているか間違っていると私に教えてください。

ありがとうございます!

答えて

60

インタフェースの継承は優れたツールですが、インターフェイスBが本当にインターフェイスAの代わりに使用できるのは、ゆるやかに関連する動作を集約するだけではありません。

具体的なケースでは適切かどうかを判断するのは難しいですが、原則として練習に間違いはありません。あなたは常に一流のAPIでそれを見ることができます。ただ一つの共通の例を選択するには、.NETフレームワークから:

public interface ICollection<T> : IEnumerable<T>, IEnumerable 
+2

私はもともとLiskov置換原則を適用することを提案しました。振り返ってみると、それは本当に関連性がありません。 LSPの要件の大部分(不変条件の維持、事前条件と事後条件の制限)は実際には具体的な実装にのみ適用でき、インタフェースには適用できません。それでも、代用性の一般的な原則は、引き続きインタフェースの継承の決定を導くべきです。 –

+0

Liskovの置換原理:インタフェースBがインタフェースAを完全に置き換えることができることを確認することが重要です。そうしないと、実装しなければならない機能が不要になります。これにより、不要なコードが発生し、ソフトウェアの安定性が低下します。 –

2

IMOこれはまさに正しいアプローチですが、私はそれに問題が表示されません。

6

インターフェイスの継承ツリーを持つことも、インターフェイスを使用して「多重継承」することも可能です。それが正しいかどうかは問題のインタフェースに依存します。実際にインタフェースBがインタフェースAの拡張または改良である場合、継承は意味をなさないが、新しいenumがインタフェースAによって表される概念とは大きく関係しない場合、それらを2つの別個のインタフェースにし、クラス両方のインタフェースを実装する必要があります。

+0

良い点は、このような状況では、関係があります。 – ajrawson

5

技術的に言えば、インターフェイスは互いに継承しません。 IFooを作成してIBarから継承すると、IFooを実装しているクラスでもIBarが実装されている必要があります。この例では

interface IBar 
{ 
    void DoBar(); 
} 

interface IFoo : IBar 
{ 
    void DoFoo(); 
} 

IFooインタフェースはDoBar()方法を持ちません。ほとんどの場合、この区別は重要ではありませんが、クラスではなくインターフェイスでリフレクションを使用すると、あなたを噛んでしまう可能性があります。

+3

Phil Haackの最近のコラム、http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspxで詳細に説明されているような振る舞いを考えても、私はそれが過度に混乱していると思います言い換えれば、C#のリファレンスドキュメントでも、「インタフェースは1つ以上の基本インタフェースから継承できる」のように、「インタフェースはお互いに継承しない」ということです。 (http://msdn.microsoft.com/en-us/library/87d83y5b%28VS.80%29.aspx)C#では、継承されたメンバーを反映​​すると、インターフェイスの継承とクラスの継承が異なる動作をする。 –

+1

十分な公正。私はそれが "継承"がどのように定義されているかに依存していると思います。確かに、C#の構文は、クラスであれインタフェースであれ、同じです。しかし、あなたが継承を親のメンバーを含むと考えると、インターフェイスについて話しているとき、あなたの精神モデルは現実とは一致しません。 –

1

は私が

IMySqlDatabase : IDatabase 
MySqlDatabase : IMySqlDatabase 

IMsSqlDatabase : IDatabase 
MsSqlDatabase : IMsSqlDatabase 

MySqlDatabaseがIMySqlDatabase ISとIMySqlDatabaseがするIDatabase IS、インタフェースは以下の別のインターフェイスの外観を継承する必要がある場合、データベースは常にそう考えると、インターフェースを実証するための素晴らしい方法を提供だと思います。

IDatabaseインターフェイスを変更する必要がある場合、それは孫です(コンクリートデータベースクラス)がメリットを享受できますが、MySQL AND MsSQL(またはさらにDBMSのインターフェイス)を展開する必要はありません。中間者(IMsSqlDatabase)と同時に、MySQLまたはOracle DBがサポートしないインターフェイス機能を引き続き使用できます。

13

インターフェイスを論理的にペアにする必要があるかどうかを検討し、相互にうまく機能すると考える場合は、継承を絶対に使用してください。

例を見てみましょう。

public interface IScanner 
{ 
    void Scan(); 
} 

public interface IPrinter 
{ 
    void Print(); 
} 

プリンタとスキャナがしばしば別のオブジェクトであるが、これら2つの装置がしばしば同じデバイスにペアリングされている独自の機能を持つ各。

public interface IPhotocopier : IScanner, IPrinter 
{ 
    void Copy(); 
} 

これは今、複写機としてのプライマリロールに加えて、複写機は、(それが含まれている)のいずれかのスキャナやプリンタとして使用されることを可能にするようIPhotocopierがIScannerとIPrinterから継承する必要があることを理にかなっています。

もう1つのインターフェイスを見てみましょう。

public interface IBlender 
{ 
    void Blend(); 
} 

それは(あなたがそれらを呼ぶもの?IBlendingScanner?)IBlenderは、以前のいずれかのインターフェイスによって継承できるようにする意味がありません。

新しいインターフェイスに分かりやすい名前を付けることができない場合は、このインスタンスで継承を使用したくない可能性があります。

IDisposableなどのインターフェイスを継承することは悪い考えです。これは、使い捨てのリソースがなくても、新しいインターフェイスのすべての実装でdisposeパターンを実装するためです。

関連する問題