2009-08-04 9 views
5

私はこの性質を持っている:オーバーライドされたプロパティにセットアクセサーを追加できないのはなぜですか?基底クラスで

public virtual string Text 
{ 
    get { return text; } 
} 

私はそれを上書きし、異なるテキストを返すようにしたいが、私は、テキストを設定できるようにしたいので、私はこれでした:

public override string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

ただし、これは機能しません。私はsetの下に赤い波打ちがあり、それは設定されたアクセサを持っていないので無効にすることはできないと言っています。なぜこれは問題なのでしょうか?私は何をすべきか?このような

+0

私は正確に同じことをしたいと思います。可能でなければならない。 –

+0

可能ですが、「中産階級」が必要です。また、多くの状況では良い考えではありませんが、抽象プロパティをオーバーライドする場合など、いくつかの例外があります。ベース: 'public abstract string Text {get; } '。中間(継承ベース): 'protected internal string text;' 'public sealed override string Text {get {return text; }} '。子(中間を継承します): 'public new string Text {get {return text; }セット{テキスト=値; }} '。保護された内部修飾子と密封されたオーバーライドは、カプセル化がアセンブリの外側で壊れていないことを保証します。 – AnorZaken

+0

@AnorZaken:これは無効になっていません。それはシャドーイングです。それは "中間"クラスを必要としません。 – Guffa

答えて

3

存在しないセットメソッドをオーバーライドしようとしますが、されている単語「オーバーライド」宣言で、コンパイラは基本クラスの同じシグネチャを持つメソッドを探します。そのメソッドを見つけることができないので、あなたのセットを作成することはできません。

ArsenMkrtによれば、ベース宣言に保護されたセットが含まれるように変更できます。これによりオーバーライドできますが、依然として署名を変更することができないため、このメソッドをサブクラスでpublicにプロモートすることはできません。したがって、投稿したコードは機能しません。

代わりに、何もしない(または試して呼び出しても例外をスローする)パブリック仮想セットメソッドを基本クラスに追加する必要がありますが、これはクラスのユーザーが期待するもの

///<summary> 
///Get the Text value of the object 
///NOTE: Setting the value is not supported by this class but may be supported by child classes 
///</summary> 
public virtual string Text 
{ 
    get { return text; } 
    set { } 
} 

//using the class 

BaseClass.Text = "Wibble"; 
if (BaseClass.Text == "Wibble") 
{ 
    //Won't get here (unless the default value is "Wibble") 
} 

は、そうでない場合は、別の方法のようにセットを宣言:あなたがこれを行う場合の動作は(と私はそれをお勧めしません)、とてもよく、ユーザはそれを見逃すことができないことを文書化されていることを確認しそうであることをあなたの子供のクラス:

public override string Text 
{ 
    get { return differentText; } 
} 

public void SetText(string value) 
{ 
    differentText = value; 
} 
+0

私はそれが好きではありませんが、私は別のSetTextメソッドや何かを持っている行に沿って何かをしなければならないと思います...ありがとう:) – Svish

+0

建築上の問題である。ユーザーが基本クラスのテキスト値を設定できないのはなぜですか?両方のクラスで*本当に*同じプロパティですか?このようなパターンが必要なのはいつもの必要条件です。 –

+0

まあ、さまざまな種類の値を保持するいくつかの異なるParameterクラスです。そして、私はそれらのすべてがユーザーが(例えば印刷のために)読むことができるテキスト値として自分自身を表すことができるようにしたいと思います。しかし、すべてのパラメータをテキストで設定することは望ましくありません(解析は印刷よりも面倒です)。たとえば、日付を印刷する日付パラメータですが、日付ピッカーで設定されるため、日付をテキストで設定する必要はありません。 – Svish

3
public virtual string Text 
{ 
    get { return text; } 
    protected set {} 
} 

変更基本クラスのプロパティは、あなたが公共のsetメソッドを作成しているコードの2番目のブロックでは

+0

保護されたセッターを子クラスのパブリックセッターとしてオーバーライドすることはできません。 – Guffa

+0

hmm、同意.... :) –

2

これは問題ですカプセル化。あなたは何かを無効にしてよりアクセスしやすくすることはできません。それはウィンドウのカプセル化に関するすべてを投げ捨てます。

これはルールであり、実際には元の値ではないものが実際に露出していても、あなたのケースでも適用されます。

試したことを正確に行う方法はありません。基本クラスでセッターを作成するか、新しい値を設定する別の方法を使用する必要があります。

public new string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

しかし、この型の変数を介してオブジェクトを操作するときに、プロパティにのみ使用されることをその場合に

、ない基本型

+0

子クラスはカプセル化がすでにベースクラスで壊れていない限り、自分がやっていることはできません。子はプロパティのバッキングフィールドにアクセスすることはできません)。また、基底クラスはそのプロパティを仮想として宣言しています。つまり、その動作を変更することが可能であることを意味します。 (もちろん、そのドキュメントを遵守している限り)仮想化されるべきかどうか、あるいはそれが基本クラスのカプセル化を破るかどうかは本当の問題です。 – AnorZaken

+0

@AnorZaken:どういうことですか?メンバーが仮想であるという理由だけで、あなたが好きな方法でそれを上書きすることはできません。 – Guffa

2

あなたは、基本クラスからプロパティを隠すことができ子タイプを使用すると、より多くの機能が公開されます。あなたが上書きしたくない、影にしたいと思うように聞こえる。新しいキーワードを使用して、読み取り専用のTextプロパティを読み書き可能なプロパティの下に隠すだけです。基底クラスで

:派生クラスで

protected string text; 
public string Text 
{ 
    get { return text; } 
} 

new public string Text 
{ 
    get { return text; } 
    set { text = value; } 
} 
2

+0

同時にシャドーしてオーバーライドすることはできますか? – Svish

+0

いいえ、それは別のものを意味します。シャドウまたはオーバーライドのどちらが、基本タイプにキャストした後でも、Textの動作が影響を受けるかどうかを決定します。より良い説明のためにこの質問をチェックしてください:http://stackoverflow.com/questions/673779/what-is-shadowing –

関連する問題