2009-09-28 11 views
19

基本抽象クラスの特定のプロパティに対してのみC#ゲッターの実装を強制したいと思います。派生クラスは、必要に応じて、静的にバインドされた型をパブリックに使用するためにそのプロパティの設定を提供することもできます。 プロパティを読み書きするための抽象readonlyプロパティをオーバーライドします。

public class Derived : Base 
{ 
    public override int Property 
    { 
     get { return field; } 
     set { field = value; } // Error : Nothing to override. 
    } 

    private int field; 
} 
をしかし、その後、私は私ので、構文エラーを取得:私もセッターを実装派生クラスを使用する場合は、私は単純に試みることができる

public abstract class Base 
{ 
    public abstract int Property { get; } 
} 

次の抽象クラスを考えると

既存のセッターをオーバーライドしてみてください。私はベースセッターをプライベートと宣言するなど、何か他の方法を試してみました。基本クラスの契約を破っていないので、これを行う方法が必要です。

私は実際には、インターフェイスで行うことができますが、私は本当にデフォルトの実装が必要です。

私はそのような状況に頻繁に遭遇しました。私はそれを行うために隠されたC#構文のトリックがあるかどうか疑問に思っていました。そうでなければ、手動のSetProperty()メソッドを実装します。

+0

クロスリンク:http://stackoverflow.com/questions/2243886/make-a-read-only-property-writable-in-the-derived-class – Mikhail

答えて

11

newoverrideと同じタイプの同じ署名を使用できないため、直接行うことはできません。 2つのオプションがあります - あなたはプロパティを追加し、基本クラスをコントロールしている場合:

public abstract class Base 
{ 
    public int Property { get { return PropertyImpl; } } 
    protected abstract int PropertyImpl {get;} 
} 
public class Derived : Base 
{ 
    public new int Property {get;set;} 
    protected override int PropertyImpl 
    { 
     get { return Property; } 
    } 
} 
エルス

あなたはクラス階層内の余分なレベルを導入することができます

public abstract class Base 
{ 
    public abstract int Property { get; } 
} 
public abstract class SecondBase : Base 
{ 
    public sealed override int Property 
    { 
     get { return PropertyImpl; } 
    } 
    protected abstract int PropertyImpl { get; } 
} 
public class Derived : SecondBase 
{ 
    public new int Property { get; set; } 

    protected override int PropertyImpl 
    { 
     get { return Property; } 
    } 
} 
+0

あなたのソリューションは面白いです、私が熟考しますそれらの上に少し。 – Coincoin

+1

あなたのソリューションは、その物に最も近いものです。しかし、派生クラスにアクロバットを強制させることなく、それを行うことは可能だとは思いません。 – Coincoin

2

何のようなものについて:

public abstract class Base 
{ 
    public virtual int Property 
    { 
     get { return this.GetProperty(); } 
     set { } 
    } 

    protected abstract int GetProperty(); 
} 
+1

すべての継承者が両方をオーバーライドする必要があります - 少し冗長ですか? –

+0

プロパティをオーバーライドする場合のみ。それ以外の場合は、実際には容認できる選択肢である可能性のある仮想的な財産はありません。 – Coincoin

+1

プロパティをオーバーライドしない場合、セットの目的は非常に珍しいです。 –

1

これはあなたのニーズに合っていますか?

public abstract class TheBase 
{ 
    public int Value 
    { 
     get; 
     protected set; 
    } 
} 
public class TheDerived : TheBase 
{ 
    public new int Value 
    { 
     get { return base.Value; } 
     set { base.Value = value; } 
    } 
} 
virtual

を除去したが、基準値は、依然として価値のためにのみ記憶装置です。これは '5'と表示されます。そして、コンパイラはおよそb.Value = 4;

TheDerived d = new TheDerived(); 
d.Value = 5; 
TheBase b = d; 
//b.Value = 4; // uncomment for compiler error 
cout << "b.Value == " << b.Value << endl; 

-Jesse

1

を大騒ぎしなければならない私は、私は2つの緩く関連するクラス間の共通の並べ替え機能を共有できるようにするインターフェースを必要と同様の要件を持っていました。そのうちの1つには読み取り専用のOrderプロパティがあり、もう1つには読み書き可能なOrderプロパティがありましたが、両方のクラスから同じ方法でプロパティを読み取る方法が必要でした。

これは、派生インターフェイスで読み取り専用の値を非表示にすることで実現できることが判明しました。ここで私がそれをした方法があります。

interface ISortable 
{ 
    int Order { get; } 
} 

interface ISortableClass2 
    : ISortable 
{ 
    // This hides the read-only member of ISortable but still satisfies the contract 
    new int Order { get; set; } 
} 

class SortableClass1 
    : ISortable 
{ 
    private readonly int order; 

    public SortableClass1(int order) 
    { 
     this.order = order; 
    } 

    #region ISortable Members 

    public int Order 
    { 
     get { return this.order; } 
    } 

    #endregion 
} 

class SortableClass2 
    : ISortableClass2 
{ 
    #region ISortableClass2 Members 

     public int Order { get; set; } 

    #endregion 
} 

class RunSorting 
{ 
    public static void Run() 
    { 
     // Test SortableClass1 
     var list1 = new List<SortableClass1>(); 

     list1.Add(new SortableClass1(6)); 
     list1.Add(new SortableClass1(1)); 
     list1.Add(new SortableClass1(5)); 
     list1.Add(new SortableClass1(2)); 
     list1.Add(new SortableClass1(4)); 
     list1.Add(new SortableClass1(3)); 

     var sorted1 = SortObjects(list1); 

     foreach (var item in sorted1) 
     { 
      Console.WriteLine("SortableClass1 order " + item.Order); 
     } 

     // Test SortableClass2 
     var list2 = new List<SortableClass2>(); 

     list2.Add(new SortableClass2() { Order = 6 }); 
     list2.Add(new SortableClass2() { Order = 2 }); 
     list2.Add(new SortableClass2() { Order = 5 }); 
     list2.Add(new SortableClass2() { Order = 1 }); 
     list2.Add(new SortableClass2() { Order = 4 }); 
     list2.Add(new SortableClass2() { Order = 3 }); 

     var sorted2 = SortObjects(list2); 

     foreach (var item in sorted2) 
     { 
      Console.WriteLine("SortableClass2 order " + item.Order); 
     } 
    } 

    private static IEnumerable<T> SortObjects<T>(IList<T> objectsToSort) where T : ISortable 
    { 
     if (objectsToSort.Any(x => x.Order != 0)) 
     { 
      return objectsToSort.OrderBy(x => x.Order); 
     } 

     return objectsToSort; 
    } 
} 
関連する問題