21

C# 仕様のセクション 10.1.1.1には、次のように記載されています。

抽象クラスには、抽象メンバーを含めることができます (必須ではありません)。

これにより、次のようなクラスを作成できます。

public abstract class A
{
    public void Main() 
    {
        // it's full of logic!
    }
}

またはさらに良い:

public abstract class A
{
    public virtual void Main() { }
}

public abstract class B : A
{
    public override sealed void Main()
    {
        // it's full of logic!
    }
}

これは実際には具象クラスです。インスタンス化できない限り、それは抽象的です。たとえば、ロジックを実行したい場合、B.Main()最初に B のインスタンスを取得する必要がありますが、これは不可能です。

継承者が実際に実装を提供する必要がない場合、なぜそれを抽象と呼ぶのでしょうか?

別の言い方をすれば、なぜ C# は具象メンバーのみを持つ抽象クラスを許可するのでしょうか?

抽象型とメンバーの意図された機能については、既に十分に理解しています。

4

9 に答える 9

23

おそらく良い例は、共通の基本クラスであり、共有プロパティと派生クラスの他のメンバーを提供しますが、具体的なオブジェクトを表していません。例えば:

public abstract class Pet
{
    public string Name{get;set;}
}

public class Dog : Pet
{
    public void Bark(){ ... }
}

すべてのペットには名前がありますが、ペット自体は抽象的な概念です。ペットのインスタンスは、犬またはその他の種類の動物でなければなりません。

ここでの違いは、実装者がオーバーライドするメソッドを提供する代わりに、すべてのペットが少なくとも 1 つのNameプロパティで構成されていることを基本クラスが宣言していることです。

于 2010-06-08T18:31:00.520 に答える
11

おそらくより特殊化された実装の基礎のみを提供することを目的としているため、実装者にクラスから派生させることを強制するという考えです。したがって、基本クラスには抽象メンバーはありませんが、拡張の基礎として使用できるコアメソッドとプロパティのみを含めることができます。

例えば:

public abstract class FourLeggedAnimal
{

    public void Walk()
    {
        // most 4 legged animals walk the same (silly example, but it works)
    }

    public void Chew()
    {

    }
}

public class Dog : FourLeggedAnimal
{
    public void Bark()
    {
    }
}

public class Cat : FourLeggedAnimal
{
    public void Purr()
    {
    }
}
于 2010-06-08T18:03:22.703 に答える
8

あなたの質問をもう少し正確に表現すると、次のようになります。C#で、具象メンバーのみの抽象クラスが許可されるのはなぜですか。

答え:そうしない理由はありません。おそらく、そこにいる誰かが、その下のクラスが単に継承して何も追加しない場合でも、インスタンス化できないクラスを一番上に配置したいという組織構造を持っています。それをサポートしない正当な理由はありません。

于 2010-06-08T18:21:56.870 に答える
3

あなたはそれを言いました-あなたはそれをインスタンス化できないからです。テンプレートのみを目的としています。

抽象として宣言した場合、それは「実際には具体的なクラス」ではありません。それはデザインの選択としてあなたに利用可能です。

その設計上の選択は、(用語が混在するリスクがある)実世界のオブジェクトの抽象化であるエンティティの作成と、読みやすさに関係している可能性があります。タイプのパラメータを宣言したいが、オブジェクトを次のように宣言可能にしたくない場合があります-タイプのすべてのオブジェクトを、、、、Carまたはとしてインスタンス化する必要があります。継承者が実装を追加する必要がないという事実は、それ自体をインスタンス化できない継承者の抽象バージョンとしての価値を損なうものではありません。CarCarTruckSedanCoupeRoadsterCar

于 2010-06-08T18:38:23.537 に答える
1

抽象とは、行動の抽象化を提供することを意味します。たとえば、Vehicleは抽象的な形式です。実世界のインスタンスはありませんが、Vehicleの動作は加速していると言えます。より具体的には、フォードイコンは車両であり、ヤマハFZは車両です。これらは両方とも加速する振る舞いをしています。

これをクラス形式で作成するとします。Vehicleは、Accelerationメソッドを使用した抽象クラスです。抽象メソッドを提供する場合と提供しない場合がありますが。ただし、ビジネス上のニーズは、Vehicleをインスタンス化しないことです。したがって、それを抽象化します。他の2つのクラス-IkonとFZは、Vehicleクラスから派生した具象クラスです。これら2つには、独自のプロパティと動作があります。

于 2010-06-08T18:39:36.080 に答える
1

使用法に関してはabstract、クラス宣言で使用するが抽象メンバーを持たないことは、クラスを持ちながらそのコンストラクターでpublic使用することと同じです。protectedどちらも、クラスをインスタンス化するためにクラスを強制的に派生させます。

ただし、自己文書化コードに関する限り、クラスをマークすることによりabstract、このクラスが単独でインスタンス化されることを意図していないことを他のユーザーに通知しvirtualますabstract。一方、コンストラクターを保護しても、そのようなアサーションは行われません。

于 2010-06-08T19:19:05.460 に答える
0

コンパイラは実装ロジックを妨げませんが、あなたの場合、私は単に抽象を省略しますか?!ところで、いくつかのメソッドはで実装でき、コンパイラは、 throw{ throw Exception("must inherit"); }だけを含む完全に実装されたクラスと関数を区別できませんでした。

于 2010-06-08T18:17:06.007 に答える
0

考えられる理由は次のとおりです。

画層スーパータイプ

レイヤー内のすべてのオブジェクトに、システム全体で複製したくないメソッドがあることは珍しくありません。このすべての動作を共通のレイヤー スーパータイプに移動できます。

--マーティン・ファウラー

抽象クラスに具象メソッドのみを持たせることを禁止する理由はありません。あまり一般的ではありません。Layer Supertypeは、これが理にかなっているケースです。

于 2010-06-08T18:53:53.637 に答える
0

抽象クラスが 2 つの主な目的を果たしていることがわかります。

  • 具体的なサービスを提供するために特殊化する必要がある不完全なクラス。ここで、抽象メンバーはオプションになります。クラスは、子クラスが使用できるいくつかのサービスを提供し、Template Method Patternのように、サービスを提供するために使用する抽象メンバーを定義できます。このタイプの抽象クラスは、継承階層を作成するためのものです。

  • 静的ユーティリティ メソッドのみを提供するクラス。この場合、抽象メンバーはまったく意味がありません。C# は静的クラスでこの概念をサポートします。静的クラスは暗黙的に抽象化され、封印されています。これは、プライベート コンストラクターを持つシール クラスでも実現できます。

于 2010-06-08T19:19:00.673 に答える