2012-02-20 2 views
5

なぜ、それ以下では有効なC#であること:プロパティが許可ではなく、抽象プロパティにインターフェースするようにアクセサを追加

public interface ISomeInterface 
{ 
    int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassImplementingInterface : ISomeInterface 
{ 
    public int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

が、これはありません:以下に

public abstract class SomeAbstractClass 
{ 
    public abstract int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassExtendingAbstractClass : SomeAbstractClass 
{ 
    public override int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

後者の結果コンパイル時エラー:

'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': cannot override because 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' does not have an overridable set accessor InterfaceAbstractTest

前者を許していない理由は何ですか?

+0

私は彼らがここでは「オーバーライド」と言います。オーバーライドする設定方法はありません。 –

+0

または、オーバーライドキーワードがアクセサレベルではなくプロパティレベルで指定されていますか?結局のところ、各アクセサは、それになると別個のメソッドです。 –

+1

右 - 抽象キーワードは、アクセサレベルではなくプロパティレベルで機能します。 –

答えて

3

インタフェースを使用して、発信者が唯一のインタフェース少なくともの実装者は述べてパブリックコントラクトを定義し、あなたの例ではSomeAbstractClassのに対し、@davisoa状態として、インタフェースの定義を実装していることを気にするので、正確にタイプ、アクセシビリティ、および(プロパティのため)メンバーの可読性/書き込み性。

reflectionを使用してSomePropertyというPropertyInfo(基本クラスまたは子クラスのいずれか)を取得する場合は、その情報をどこかから解決する必要があります。子クラスに可読性/可読性を変更させることは、戻り型や引数リストの変更と同じくらい契約違反になります。

例えば想像:必要である

SomeAbstractClass sc = new SomeClassExtendingAbstractClass(); 
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty"); 
Console.Out.WriteLine(pi.CanWrite); // What should be printed here? 
2

これは、Interfaceインプリメンテーションが「Get」できるプロパティSomePropertyが存在することを約束しているためです。

抽象クラスの実装では、それが子クラスでpublicメソッドgetの実装を提供することを約束しています。インタフェースは契約を定義している一方の端部において

、基底クラスは、をオーバーライドしなければならない何かを定義しています。

+0

私が心配している限り、 'SomeClassExtendingAbstractClass' *は、プロパティ' SomeProperty'にパブリックgetメソッドを提供します。抽象的なインタフェースに対して作業する人にとっては、セッターも存在することは重要ではありません。したがって、私の質問。 get/setのそれぞれが代わりにメソッドであると想像してください。 'GetValue'メソッドを持つ抽象クラスを拡張しただけなので、' SetValue'メソッドを提供できないとしましょう。 –

+2

@KentBoogaartそれはものです。彼らはゲッターやセッターだけではありません。プロパティは.NETの一流の市民であり、プロパティに関連付けられた読みやすさ/書き込み可能性に関する契約メタデータを持っています。 –

1

存在しないセット演算子をオーバーライドしようとしています。抽象クラスでプロパティの設定部分を定義するか、具象クラスで定義しようとしないでください。あなたはコンクリートクラスで保護されたセットを持っているので、抽象定義で保護された集合演算子を作っていると思います。

0

何が既存のプロパティをオーバーライドして、新しい読み書き1でそれをシャドウの両方です。残念ながら、.netは、単一のクラス内のメンバのオーバーライドとシャドーイングの手段を提供していません。最良の方法は、抽象基本クラスに抽象関数を呼び出す具体的な非仮想の読み取り専用プロパティを定義させることです。派生クラスは、そのゲッターで同じ関数を呼び出す非仮想の読み書き可能な関数と、そのセッターで新しい抽象関数または仮想関数を使用してプロパティをシャドーすることができます。

1

これは仕様です。私はC#言語仕様から引用しています:

An overriding property declaration must specify the exact same accessibility modifiers, types and name as the inherited property, if the inherited property has only a single accessor (i.e.,... ready only or write-only), the overriding property must include only that accessor.

インターフェースは、より柔軟に抽象クラスよりも契約の一種であるため、そのdecesionの背後にある理由はある可能性があります。インタフェースは、実装全体ではなく、最小公約数についてのみ気にします。あるデザインを他のデザインよりも選択する理由があると思います。

関連する問題