インターフェイスを定義してから、コードはそのインターフェイスを実装するオブジェクトのみを受け入れる必要があります。共通の基本クラスを使用して作成することは非常に魅力的ですがabstract
、このアプローチは定義上 (ほぼ) 間違っています。
多重継承を許可しない C# やその他の言語では、他のユーザーが埋めなければならない空の「スケルトン」を定義するためだけに基本クラスを作成し、全員にそれを使用させることは非常に制限的です。誰もがそれを継承する必要があるため、たとえば、独自の既存のクラス階層を再利用したり、面倒なブリッジを作成したり (...) する必要はありません。
抽象基本クラスに、1/数/ダース/数百の抽象メソッド、イベント、およびプロパティ以外に何もない場合は、「共通の要件」のみを定義するため、インターフェイスである必要があります。
共通のもので新しい抽象ベースを作成する唯一の合理的な理由は、実際にデフォルトの実装を提供することです。それでも、そのような基本クラスでは、インターフェイスも定義する必要があります。基本はそれを実装し、オーバーライドを許可し、実際には抽象として何かをマークすることさえできますが、コードは基本クラスではなく、インターフェイスを介してすべてを参照する必要があります。このような抽象ベースは、必須ではなく、実装者のヘルプ/ショートカットであるべきです。誰かがゼロからすべてをやりたい場合 - 彼はインターフェイスを実装し、サンプルコードでベースを無視します. それでも、すべての共通コードは、まさにそのインターフェイス上で動作する一連の静的ヘルパー クラスとして提供される場合があります。
抽象基本クラスは実際には必要であり、たとえば、派生クラスにパラメーター付きのコンストラクターを持たせる必要がある場合や、何かから派生する必要がある場合など、いくつかのコーナーケースではインターフェイスに取って代わることはできません。WPF Visual または UIElement または DependencyObject のように --- したがって、Microsoft の設計には、ここでも少し欠陥があります。彼らは基本クラスからの派生を強制し、多くの場所で開発者に影響を与えました (たとえば、EntityFramework のデータ モデル オブジェクトが DependencyObject ではないなど)。それでも、私は彼らがそこから抽象化すべきだったと思います - Visual とその友人を見て、インターフェイスに持ち上げることができなかった多くの内部ルーチンはありません..パフォーマンスについてであり、キャスト/メソッドのディスパッチを削減することでした。
私が言ったことはすべて、あなたが質問で提示したものと正確に一致しないことに注意してください. そこでは、すでに「親/基本クラスが XYZ を処理する」と想定しています。これは、インターフェイス アプローチを最初からやめていることを意味します。インターフェイスでは、クリックとキャンセルクリックが存在する必要があることのみを定義しますが、「基本実装」を強制/提供することはできません。このようなことは、基本クラスで実行できます。したがって、オープン/混合アプローチを採用する必要があると思います。インターフェイスを定義し、静的な再利用可能なハンドラーを定義し、インターフェイスのみを使用し、一部の「怠惰なコーダー」に基本クラスを提供します。
public interface IClickable
{
ICommand CancelCommand { get; }
void CancelClick();
bool CanCancelClick();
}
public static class ClickableDefaultImpl
{
public static void DefaultCancelClick(IClickable obj)
{
... do the common things on the OBJ
}
public static bool DefaultCanCancelClick(IClickable obj)
{
... do the common things on the OBJ
}
}
public abstract class Clickable : IClickable
{
public void CancelClick() { ClickableDefaultImpl.CancelClick(this); }
public bool CanCancelClick() { return ClickableDefaultImpl.CanCancelClick(this); }
}
これは非常に肥大化しているように見えるかもしれませんが、カスタマイズの余地はかなりあります。オープン性はありますが、全員が「ClickableImpl」を使用する必要があることを強制する方法はほとんどありません。いくつかの方法がありますが、..それらにはさらに肥大化と時間/メモリのオーバーヘッドが含まれます。今説明する価値はないと思います。
将来、誰が、どのように、どのくらいこのコードを使用するかを見積もることを忘れないでください。1 回、2 回、5 回使用する場合は、抽象的なベースを使用してください。しかし、数十または数百の子実装を感知した場合は、少し肥大化したほうがよいでしょう。後で時間を大幅に節約できます。