2011-07-21 8 views
1

私はC#と継承に関する簡単な基本的な質問があります。基本クラスの必須セットプロパティを実装する最良の方法は何ですか?

以下の例では、Iは設定の2つの方法を示していプロパティ(CaptionDisplayTextとファーストネーム)を設定する必要があります

public abstract class BaseClass 
{ 
    private string _firstName; 

    protected BaseClass(string captionDisplayText) 
    { 
     this.CaptionDisplayText = captionDisplayText; 

     this._firstName = this.GetFirstName(); 
    } 

    protected string CaptionDisplayText { get; private set; } 

    protected abstract string GetFirstName(); 
} 

public class DerivedClass : BaseClass 
{ 
    protected DerivedClass():base(String.Empty) 
    { 

    } 

    protected override string GetFirstName() 
    { 
     return String.Empty; 
    } 
} 

アプローチ1、CaptionDisplayTextは、アプローチに対し性を紹介し、コンストラクタに設定します2では、Derivedクラスでオーバーライドされた抽象メソッドを導入しています。

私はApproach2が抽象的ではなく仮想であった場合には悪いことを知っていますが、ここでは抽象型です。つまり、基本クラスのコンストラクタの前に実行され、それは問題ありません。

私は10-15のプロパティ/フィールドを派生クラスで設定する必要がありますので、どのアプローチがより保守性が高く、読みやすく、テスト可能であるか考えています。

アプローチ1はよりテスト可能であり、アプローチ2ははるかに読みやすいと思う。アプローチ2は、モックオブジェクトが抽象メンバを実装しなければならないため、テスト可能です。

あなたの見解にはどのような方法があり、3番目の方法がありますか?

多くのおかげで、

+0

null可能な文字列を使用します。これは、基本的に、クラスを使用した誰もがこの事実を認識するように強制します。プロパティが値を持つことを要求しようとするのは、まさに目的です。私はこれが何らかの図書館だと思いますか? –

答えて

0

クラスをテスト可能にしたい場合は、コンストラクタのロジックを実行することはできません。だからthis._firstName = this.GetFirstName();あなたが最初の名前で何もしたくない場合でも、コードが呼び出されます。最初のアプローチでは、あなたのテストでは重要ではないことを示すヌルで埋めることができます。

+0

あなたの見解に感謝しますが、コンストラクタでインスタンス化される10-15のプロパティを持つと、(醜い=いいえ)広いコンストラクタを与えるでしょう。 –

0

あなたはCodeContractsとClassInvariantを使用して考えがありますか?

+0

2008年の会議でcodecontractsを最初に見ましたが、マイクロソフトの人々が調査を開始したときには、ここでの質問ではなく、適切なパラメータがメソッドに渡されているかどうかを確認することが重要です。 –

+0

@William [MSDN Code Contracts](http://msdn.microsoft.com/en-us/library/dd412890.aspx)を参照してください。コードコントラクトは、インバリアントとパラメータの検証もサポートしています。 –

0

私にとっては、オブジェクトの構築中に強制的に設定する必要があるデータを明示的に設定し、呼び出し元に情報を提供するため、1番目に優れています。

あなたがここで満たすことができる唯一の「問題」は、ある時点で、ctorのパラメータのように、1つの方法で15個のパラメータを表示するのに不思議な量のプロパティです。しかし、いくつかのプロパティ値セットから他のプロパティの "デフォルト"値を差し引くことができれば、ctorのオーバーロードによってこれが(あなたのアプリを知らずにわかりにくい) "避ける"ことができるかもしれません。

Dictionary/HashSetなどのソリューションもありますが、私にとっては解決策も邪魔です。

これが役に立ちます。

よろしくお願いいたします。

0

私にとっては、これは混乱しています。なぜGetFirstNameを使ってファーストネームを設定していますか?これを抽象的なSetFirstNameメソッドとして行い、コンストラクタに隠す代わりにその中でロジックを実行する方が良いでしょうか?私はそれを行うのは難しい/良い方法だと思うが、一部の人には混乱するかもしれない。 GetFirstNameメソッドを実装するときに派生クラスでは、基本クラスでこれを設定する直感的ではありません。

保護された抽象的な文字列のようなものSetFirstName();このように、派生クラスは常にこのメソッドをオーバーライドし、その中にファーストネームを設定する必要があります。もちろん、firstnameプロパティを保護しなければなりません。

「必須設定」アプローチではありません。しかし、少なくともあなたにヒントを与えます。または、おそらくGetFirstNameをSetFirstNameに変更してください)

+0

ありがとうが、SetFirstName()抽象メソッドを提供しても、FirstNameが派生クラスとして設定されていることは保証されません。それで私はこのオプションについて言及しなかったのです。 –

+0

しかし、私は2つの利点があると思います:1)優れた可読性2)コンストラクタをきれいに保つ:プロパティが設定されていることを保証しません。 –

+0

私は全く同意します。プロパティの設定を保証するものではありません。しかし、派生クラスはget firstnameメソッドを空のままにして、使用されていないと考えることもできます。 –

関連する問題