web-dev-qa-db-ja.com

いつ抽象プロパティを使用するか、いつ使用しないかわからない

何がよく見えるか、いつ抽象クラスとプロパティで実際に使用するのか、または非抽象プロパティをいつ使用するのかはよくわかりません。簡単な例を作ってみます。私がこれを持っているとしましょう:

abstract class Human
{
  public GenderType Gender { get; set; }
  public string Name { get; set; }
  public Date Born { get; set; }
  public bool IsNerd { get; set; }

  abstract public void Speak();
  abstract public void Sleep();
  abstract public void AnoyingPeopleOnStackOverflow();
  //... so on
}

class Peter : Human
{
  //Peter is special, he got a second name
  //But thats all, everything else is the same as like on other humans
  public string SecondName { get; set; }

  //...override abstract stuff
}

これでいいですか?私が理解したように、抽象プロパティをオーバーライドしたくない場合は、抽象プロパティを使用する必要はありません。この状況では大丈夫です。SpeakSleepなどのメソッドだけが抽象的である必要があります。

さて、これで問題なければ、いつ抽象プロパティを使用するか、または使用する必要がありますか?

39
miri

デフォルトの実装がなく、派生クラスがそれを実装する必要がある場合は、抽象プロパティを使用します。

基本クラスに実装があるが、オーバーライドを許可する場合は、仮想プロパティを使用します。

overrideキーワードを使用して、メンバーをオーバーライドします。メンバーを再度オーバーライドしない場合は、sealed overrideとしてマークします。

プロパティを上書きしたくない場合は、プロパティをabstractまたはvirtualとしてマークしないでください。

newキーワードを使用して、非抽象、非仮想メンバーを非表示にします(これはめったに良いアイデアではありません)。

方法:抽象プロパティを定義する

抽象プロパティは、タイプ固有のロジックや副作用があることを意味するデザインでしばしば発生することがわかります。基本的に、「すべてのサブクラスに必要なデータポイントがありますが、実装方法がわかりません」と言っています。 ただし、、大量のロジックを含むプロパティや副作用を引き起こすプロパティは望ましくない場合があります。これは重要な考慮事項ですが、正しい/間違った方法はありません。

見る:

個人的には、抽象メソッドを頻繁に使用しますが、抽象プロパティはめったに使用しません。

74
Tim Medora

私は彼らに何をしてほしいかを知っています、彼らがそれをどうするかは気にしません:インターフェース。

私は彼らが何をしたいのか知っています、彼らがそれをどうやってやるかは気にしませんが、私は彼らが他のビット(または少なくともほとんど)をどのように行うかについてしっかりと考えています:抽象クラス。

私は彼らに何をしたいのか、そして彼らのほとんどがそれをどのように行うのかを知っています:仮想メンバーを持つ具体的なクラス。

他のケース、たとえば抽象メンバーを持たない抽象クラス(1つのインスタンスを持つことはできませんが、どの機能を提供するか、完全に提供します)が、特定の階層が特定の階層にきれいに露骨に提供されるため、それらはよりまれで通常発生します問題。

(ちなみに、私はピーターを人間のタイプとは思わず、各ピーターをたまたまピーターと呼ばれる人間のインスタンスと考えます。このようにサンプルコードを選ぶのは本当に公平ではありませんが、この種の問題について考えると、それは通常よりも適切です)。

28
Jon Hanna

抽象メンバーは、オーバーライドする必要がある単なる仮想メンバーです。これは、実装する必要があるが、基本クラスには実装できないものに使用します。

仮想プロパティを作成し、クラスを継承するクラスでオーバーライドする必要がある場合は、それを抽象プロパティにします。

たとえば動物のクラスがある場合、呼吸する能力は、それが動物であるという情報だけから判断することはできませんが、それは非常に重要なことです:

public abstract class Animal {

  public abstract bool CanBreathe { get; }

}

魚と犬の場合、実装は異なります。

public class Dog : Animal {

   public override bool CanBreathe { get { return !IsUnderWater; } }

}

public class Fish : Animal {

   public override bool CanBreathe { get { return IsUnderWater; } }

}
13
Guffa

すべてのサブクラスhaveの場合、abstractを使用してメソッド/プロパティを実装します。サブクラスごとに実装する必要がない場合は、使用しないでください。

あなたの例として、各人にSecondNameが必要ない場合、基本クラスに抽象プロパティを作成する必要はありません。一方、すべての人が2番目の名前を必要とする場合、それを抽象プロパティにします。

抽象プロパティの正しい使用例:

public class Car
{
    public abstract string Manufacturer { get; }
}

public class Odyssey : Car
{
    public override string Manufacturer
    {
         get 
         {
             return "Honda";
         }
    }
}

public class Camry : Car
{
    public override string Manufacturer
    {
         get 
         {
             return "Toyota";
         }
    }
}

every車にはメーカーがあり、そのメーカーをユーザーに伝えることができる必要があるため、Maker abstractを作成するのは正しいことです。

4
Daniel

クラスに常にプロパティを公開させたいが、そのプロパティの実装を固定できない場合、抽象クラスのプロパティを使用します-継承クラスにそれを任せる/強制する。

例があります here 、抽象クラスの名前はShapeで、抽象Areaプロパティを公開します。面積の式は形状のタイプごとに変わるため、基本クラスにAreaプロパティを実装することはできません。すべての図形には(何らかの)領域があるため、すべての図形にプロパティを公開する必要があります。

実装自体は問題ありません。 Humanの抽象プロパティの賢明な例を考えようとしていましたが、合理的なものは考えられませんでした。

1
Jon Egerton