私は番号を持っているProcessor
クラスは2つの非常に異なることをしますが、共通コードから呼び出されます(「制御の逆転」の状況)。
私は、あなたがすべてを継承すべきかどうかを決める際に、どのような設計上の考慮事項を私が認知するべきであるか(あるいは、あなたがUSSのために認識している)BaseProcessor
、または実装するIProcessor
インターフェイスとして。
一般に、ルールは次のようになります。
これをもっと具体的に言えば、例を見てみましょう。ザSystem.Drawing.Bitmap
クラスis-anイメージ(そして、そのように、それはImage
クラス)が、それもできる処分するので、IDisposable
インタフェース。またできるシリアライゼーションは、ISerializable
インタフェース。
しかしもっと実際的には、C#では複数の継承をシミュレートするためにインターフェースがよく使われます。もしあなたのProcessor
クラスは次のようなものから継承する必要がありますSystem.ComponentModel.Component
、あなたはほとんど選択肢がありませんが、IProcessor
インタフェース。
実際には、インターフェースと抽象基本クラスの両方が、特定のクラスが何を行うことができるかを指定するコントラクトを提供します。この契約を宣言するためにインタフェースが必要であるという共通の神話ですが、それは正しくありません。私の心の最大の利点は、抽象基本クラスでサブクラスにデフォルトの機能を提供できることです。しかし、意味のあるデフォルトの機能がない場合、メソッド自体を次のようにマークすることはできません。abstract
インタフェースを実装する場合と同様に、派生クラス自身で実装する必要があります。
このような質問に対する回答については、.NET Frameworkデザインガイドラインこれは、クラスとインタフェースの選択について言います。
一般に、クラスは抽象を公開するための好ましい構築物です。
インターフェイスの主な欠点は、APIの進化を許容するという点で、クラスよりもはるかに柔軟性がないということです。インターフェイスを出荷すると、メンバーのセットは永久に固定されます。インタフェースへの追加は、そのインタフェースを実装する既存の型を破壊します。
クラスはもっと柔軟性を提供します。すでに出荷されたクラスにメンバーを追加することができます。メソッドが抽象メソッドでない限り(つまり、メソッドのデフォルト実装を提供している限り)、既存の派生クラスは変更されずにそのまま機能します。
[。 。 。 ]
インタフェースを優先する最も一般的な主張の1つは、実装から契約を分離できることです。しかし、引数は、クラスを使用して実装から実装を分離できないと誤って想定しています。具体的な実装とは別のアセンブリにある抽象クラスは、そのような分離を実現するための素晴らしい方法です。
一般的な推奨事項は次のとおりです。
クリス・アンダーソンは、この最後の教義との特定の合意を表明し、
抽象型はバージョンをはるかに良くし、将来の拡張性を可能にしますが、基本型のみを焼き付けます。インタフェースは、時間の経過とともに不変である2つのオブジェクト間のコントラクトを実際に定義するときに適切です。抽象基本型は、型のファミリの共通基底を定義するのに適しています。
リチャード、
なぜそれらの間を選ぶのですか?私はIProcessorインターフェイスを持っています出版されたタイプ(システムの他の場所で使用するため)。そのようにしてIProcessorのさまざまなCURRENT実装が共通の振る舞いを持つ場合、抽象的なBaseProcessorクラスはその共通の振る舞いを実装するための本当の良い場所になります。
このようにして、将来、BaseProcessorのサービス用ではなかったIProcessorが必要な場合、それを持っていなくても(おそらくそれを隠していなくても)...しかし、それを望む人は、重複したコード/コンセプトで
ちょうど私の謙虚な意見。
乾杯。キース。
インターフェースは「契約」です。これらは、クラス、つまりプロパティ、メソッド、イベントなどのメンバーを実装するクラスです。
基本クラス(具体的または抽象的ではない)は、あるエンティティの原型です。これは、実際の物理的または概念的なものに共通するものを表すエンティティです。
いつインターフェイスを使用するのですか?
いくつかのタイプは、少なくとも、消費者が気にするべきいくつかの振る舞いと性質を持っていることを宣言する必要があるときはいつでも、それを使って何らかの仕事を達成する。
ベースクラス(具体的および/または抽象的)を使用する場合は、
あるグループのエンティティが同じアーキタイプを共有する場合、BはAが相違しているためAを継承しますが、BはAと識別できます。
例:
テーブルについて話しましょう。
リサイクル可能なテーブルを受け入れる=>これは "IRecyclableTable"のようなインタフェースで定義しなければならず、すべてのリサイクル可能なテーブルに "リサイクル"メソッド。
デスクトップテーブルが必要です=>これは継承で定義する必要があります。 「デスクトップテーブル」は「テーブル」です。すべてのテーブルには共通のプロパティと動作があり、デスクトップには共通のプロパティと動作があり、デスクトップテーブルが他のタイプのテーブルとは異なる動作をするようなものが追加されます。
私はアソシエーションについて話すことができます。つまり、オブジェクトグラフの両方の場合の意味ですが、私の大胆な意見では、概念的な観点から議論を行う必要がある場合、私はこの議論で正解します。
IRecyclable
インターフェイスとは無関係オブジェクトはリサイクル可能である必要があります(つまり、表を表さない他のクラス)。そして、私はまだすべてのテーブルをTable
クラスを含むDesktopTable
そしてPicnicTable
そしてFoldingTable
。 - Cody Gray♦
私は設計上の選択肢があまりよくありませんが、尋ねられれば、拡張するメンバーだけがあればiProcessorインターフェースを実装する方が好きです。拡張する必要のない他の関数がある場合は、ベースプロセッサーから継承するほうがよいでしょう。
デザインの純度をさておき、一度しか継承することはできません。フレームワーククラスを継承する必要がある場合は疑問があります。
あなたが選択肢がある場合、実際には最も入力を節約するオプションを選択することができます。とにかく純粋な選択です。
編集:
基本クラスがある実装を持つなら、これは有用かもしれません、純粋にabstactであれば、それはインタフェースかもしれません。
選択した項目が問題でない場合は、常に[インタフェース]を選択します。より柔軟に対応できます。将来の変更から保護するかもしれません(基本クラスで何かを変更する必要がある場合、継承されたクラスが影響を受ける可能性があります)。また、詳細をカプセル化することもできます。あなたがDependency Injectionの制御の反転を使用している場合、彼らはインターフェイスを好む傾向があります。
継承を避けることができない場合は、両方を一緒に使用することをお勧めします。インタフェースを実装する抽象基本クラスを作成します。あなたの場合、ProcessorBaseはIProcessorを実装します。
ASP.NET MVCのControllerBaseおよびIControllerに似ています。
SOLIDの原則がプロジェクトの保守性と拡張性を向上させることを考えれば、継承よりもインターフェイスを優先したいと思います。
また、インターフェイスに「追加機能」を追加する必要がある場合は、インターフェイス・セグレゲーションの原則であるSOLIDのIに従って、新しいインターフェイスを作成することをお勧めします。