2017-06-19 9 views
2

プロパティとメソッドの実装を変更したい基本クラスから継承するクラスがいくつかあります。私はまた、基本クラスとすべてのサブクラスがポリモーフィックであることを要求するので、後で特定のインタフェースを実装する任意の型のコレクションを作成することができます。ポリモーフィズムを維持しながら、サブクラスのプロパティアクセサを変更する適切な方法は何ですか?

インターフェイスを実装するクラスのインスタンスを作成するとき、そのクラス(インターフェイスで実装されています)で基本クラスではなくプロパティとメソッドを使用します。

これで所望の出力を提供しますが、コードのにおいを持っている問題の私の簡素化実現...これは動作しますが、コントロールクラスの空のセットを持つ少し汚い感じ

class Program 
{ 
    static void Main(string[] args) 
    { 
     IGrid one = new TextField(); 
     IGrid two = new SelectList(); 
     one.Click(); 
     two.Click(); 
     Console.WriteLine(one.Text); 
     Console.WriteLine(two.Text); 
     Console.ReadLine(); 
    } 
} 

public interface IGrid { 
    string Text { get; set; } 
    void Click(); 
} 

public class Control : IGrid { 
    public string Text { 
     get { return "Hello Control!"; } 
     set { } 
    } 

    public virtual void Click() { 
     Console.WriteLine("In the Control!"); 
    } 
} 

public class SelectList : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello Select!"; 
     } 
     set { Number = int.Parse(value); } 
    } 

    public override void Click() { 
     Console.WriteLine("In the Select!"); 
    } 
} 

public class TextField : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello TextField!"; 
     } 
     set { Number = int.Parse(value); } 
     } 

    public override void Click() 
    { 
     Console.WriteLine("In the TextField!"); 
    } 
} 

サブクラスの特定のプロパティの実装を妥協することなく、このタイプの問題に対して明確なアプローチがありますか?

多くのおかげで、

+1

IMHO、インターフェイスを実装しない場合は、インターフェイスを実装しようとしないでください。あなたのクラスのエンドユーザーにいくつかの思いやりを持ってください。また、あなたの例は私には意味がありません。つまり、文字列 'Text'プロパティを非整数値に設定しようとすると例外がスローされます。2.あなたは' Text'プロパティを変更しません誰かがそれを設定するとき。もっと現実的な例がありますか?追加のプロパティを持つ新しいインターフェイスを作成するのではなく、なぜこれをやりたいのかは完全にはっきりしていません。 –

+0

こんにちはRufus。申し訳ありませんが、それは明確ではありません。まだ勉強してる。最終的に 'List GridItems'のようなもので終わり、' SelectList'や 'TextField'のような異なるタイプのグリッド項目を追加できるようにしたいと思います。私はそれらのクラスのメソッドとプロパティの特定の実装にアクセスできるようにしたいと思います。変わったように見える 'set'アセスメントは、サブクラスの実装を変更したいことを示すためだけにあります。私が言うように、アプローチは完全に間違っている可能性があり、私はより良い提案には開いています。ありがとう、 – Konzy262

答えて

1

わかりましたので、最初のものは、最初に(あなたがテキストから数値にやっているように)あなたがプロパティを設定するときには、別のプロパティを変更すべきではありません。これは副作用であるため、巨大なコードの匂いです。あなたは常にあなたが意図しているプロパティを直接扱うべきです。

public class SelectList : Control, IGrid { 
    public int Number { get; set; } 
    public new string Text { 
     get { 
      return "Hello Select!"; 
     } 
     // This is bad, someone after you may not know that this has a side effect 
     set { Number = int.Parse(value); } 
    } 
} 

第二に、財産はとても仮想としてあなたのTextプロパティをマークし、多型は、それが意図されている方法を動作させるでしょう派生クラスでオーバーライドするだけの方法と同様に仮想することができます。新しいキーワードを使用して「非表示」するには、そのクラスの実装を取得するために、インターフェイスにその特定のクラスをキャストする必要があります。

public class Control : IGrid 
    { 
     public virtual string Text 
     { 
      get { return "Hello Control!"; } 

     } 

     public virtual void Click() 
     { 
      Console.WriteLine("In the Control!"); 
     } 
    } 
public class SelectList : Control, IGrid 
{ 
    public int Number { get; set; } 
    public override string Text 
    { 
     get 
     { 
      return "Hello Select!"; 
     } 

    } 

    public override void Click() 
    { 
     Console.WriteLine("In the Select!"); 
    } 
} 

第3に、インターフェイスにセッターを持つ必要はありません。あなたはゲッターを持っていて、それを実装する必要があります。あなたは常にメソッドやプロパティをオーバーライドするつもりはないし、絶対に(新しいと)直接基本クラスを作成しようとしている場合は、実装(EGで共有している場合

public interface IGrid 
    { 
     string Text { get; } 
     void Click(); 
    } 

最後に、あなたは、抽象クラスを使用することを検討すべきです少なくとも1つのメソッドやプロパティを変更しないでください)、いずれにしてもコードを一切使用していないため、基本クラスを気にしないでください。

// Abstract class 
public abstract class Control : IGrid 
{ 
    // Property that is not overridden but is shared 
    public int Number { get; set; } 

    public abstract string Text 
    { 
     get; 

    } 

    public abstract void Click(); 
} 
public class SelectList : Control 
{ 
    // Don't need the Number property here, base class has it 

    public override string Text 
    { 
     get 
     { 
      return "Hello Select!"; 
     } 

    } 

    public override void Click() 
    { 
     Console.WriteLine("In the Select!"); 
    } 
} 

// Need everything in this class, but if it is all different anyways 
// then base class is kind of a waste 
public class TextField : IGrid 
{ 
    public int Number { get; set; } 
    public string Text 
    { 
     get 
     { 
      return "Hello TextField!"; 
     } 
    } 

    public void Click() 
    { 
     Console.WriteLine("In the TextField!"); 
    } 
}