web-dev-qa-db-ja.com

C#の抽象クラスのコンストラクター

C#で抽象クラスのコンストラクターを作成できるのはなぜですか?
私が知る限り、抽象クラスをインスタンス化することはできません。
クラスをインスタンス化することはできませんか?

182
Mulder

抽象クラスでデータをインスタンス化する標準的な方法があるかもしれないからです。そうすれば、そのクラスから継承するクラスにベースコンストラクターを呼び出させることができます。

public abstract class A{

    private string data;

    protected A(string myString){
      data = myString;
    }

}

public class B : A {

     B(string myString) : base(myString){}

}
229
Craig Suchanec

私が知っている限りでは、抽象クラスをインスタンス化することはできません

そこにエラーがあります。 もちろん、抽象クラスをインスタンス化できます。

abstract class Animal {}
class Giraffe : Animal {}
...
Animal animal = new Giraffe();

Animalのインスタンスがすぐそこにあります。抽象クラスをインスタンス化するには、それから派生した具体的なクラスを作成し、それをインスタンス化します。派生した具象クラスのインスタンスは、also抽象基底クラスのインスタンスであることを忘れないでくださいAnimalが抽象的であっても、GiraffeのインスタンスはAnimalのインスタンスでもあります。

抽象クラスをインスタンス化できることを考えると、その不変条件が満たされることを保証するために、他のクラスのようなコンストラクターが必要です。

さて、staticクラスは実際にはインスタンス化できないクラスであり、静的クラスでインスタンスコンストラクターを作成することは違法であることに気付くでしょう。 。

258
Eric Lippert

これは、抽象クラスの不変式のセットを強制する方法です。つまり、サブクラスが何をしていても、いくつかの事柄が基本クラスに常に当てはまることを確認したい...例:

abstract class Foo
{
    public DateTime TimeCreated {get; private set;}

    protected Foo()
    {
         this.TimeCreated = DateTime.Now;
    }
}

abstract class Bar : Foo
{
    public Bar() : base() //Bar's constructor's must call Foo's parameterless constructor.
    { }
}

コンストラクターをnew演算子の双対と考えないでください。コンストラクターの唯一の目的は、使用を開始する前にオブジェクトが有効な状態にあることを確認することです。それはたまたま通常new演算子で呼び出すことです。

20
Rodrick Chapman

抽象クラスのすべての実装、または抽象クラスに実装したメソッドに必要な初期化ロジックを強制するためにあります(抽象クラ​​スのすべてのメソッドが抽象である必要はなく、実装できるメソッドもあります)。

抽象基本クラスを継承するクラスは、基本コンストラクターを呼び出す必要があります。

5
Ross Anderson

通常、コンストラクターには、作成されるオブジェクトのメンバーの初期化が含まれます。継承の概念では、通常、継承階層の各クラスコンストラクターは、独自のメンバー変数をインスタンス化します。変数が定義されている場所でインスタンス化を行う必要があるため、これは理にかなっています。

抽象クラスは(インターフェイスとは異なり)完全に抽象ではないため、抽象メンバーと具象メンバーの両方が混在しているため、抽象クラスのコンストラクターで行われる抽象でないメンバーを初期化する必要があるため、コンストラクターが必要です抽象クラス。もちろん、抽象クラスのコンストラクターは、派生クラスのコンストラクターからのみ呼び出すことができます。

1
Zafar Ameem

継承可能な具象クラスThingのパブリックまたは内部ストレージクラスでコンストラクターを定義すると、2つのメソッドが効果的に定義されます。

  • InitializeThingに作用し、戻り値がなく、thisThingおよびCreateThingメソッド、およびサブクラスのInitializeThingメソッドからのみ呼び出すことができるメソッド(InitializeXXXを呼び出します)。

  • メソッド(私はCreateThingと呼びます)は、コンストラクターの指定された型のオブジェクトを返し、基本的に次のように動作します:

    Thing CreateThing(int whatever)
    {
        Thing result = AllocateObject<Thing>();
        Thing.initializeThing(whatever);
    }
    

抽象クラスは、最初の形式のメソッドのみを効率的に作成します。概念的には、上記の2つの「メソッド」が同じアクセス指定子を持つ必要がある理由はありません。ただし、実際には、アクセシビリティを異なる方法で指定する方法はありません。実際の実装に関しては、少なくとも.NETでは、CreateThingは実際には呼び出し可能なメソッドとして実装されているのではなく、newThing = new Thing(23);ステートメントで挿入されるコードシーケンスを表していることに注意してください。

0
supercat

抽象クラスには、初期化が必要なメンバー変数を含めることができます。したがって、抽象クラスコンストラクターで初期化でき、派生クラスオブジェクトが初期化されると、このコンストラクターが呼び出されます。

0
waqar ahmed

から https://msdn.Microsoft.com/en-us/library/ms182126.aspx

抽象型のコンストラクターは、派生型によってのみ呼び出すことができます。パブリックコンストラクターは型のインスタンスを作成し、抽象型のインスタンスを作成できないため、パブリックコンストラクターを持つ抽象型は誤って設計されています。

派生クラスのみが抽象クラスコンストラクターを使用できるため、必要に応じて抽象クラスコンストラクターをprotectedとして宣言する必要があります。

ただし、抽象クラスでパブリックコンストラクターを宣言する場合、VSコンパイラーは(デフォルトルールで)文句を言いませんが、新しいインスタンスの作成は許可しません。

0
Ahmad

私も抽象的な表面に輝きを与えたいと思っています。すべての答えはほぼすべてをカバーしています。それでも私の2セント

抽象クラスは通常のクラスですが、いくつかの例外があります

  1. そのクラスのクライアント/コンシューマーは、そのクラスのオブジェクトを作成できません。それは、コンストラクターが呼び出さないことを意味するものではありません。その派生クラスは、呼び出すコンストラクターを選択できます。
  2. それは抽象的な機能を持っているかもしれません。
0
Sumit Kapadia

あなたは絶対に正しいです。抽象メソッドには本体がないため、抽象クラスをインスタンス化できません。つまり、抽象メソッドの実装は不可能です。ただし、基本クラスの変数を初期化するシナリオがいくつかある場合があります。 @Rodrickが提案するbaseキーワードを使用して、これを行うことができます。このような場合、抽象クラスでコンストラクターを使用する必要があります。

0
Rohan Rao

すべてのメソッドを実装した後、インスタンス化できます。次に、コンストラクターが呼び出されます。

0
duedl0r