C#で抽象クラスのコンストラクターを作成できるのはなぜですか?
私が知る限り、抽象クラスをインスタンス化することはできません。
クラスをインスタンス化することはできませんか?
抽象クラスでデータをインスタンス化する標準的な方法があるかもしれないからです。そうすれば、そのクラスから継承するクラスにベースコンストラクターを呼び出させることができます。
public abstract class A{
private string data;
protected A(string myString){
data = myString;
}
}
public class B : A {
B(string myString) : base(myString){}
}
私が知っている限りでは、抽象クラスをインスタンス化することはできません
そこにエラーがあります。 もちろん、抽象クラスをインスタンス化できます。
abstract class Animal {}
class Giraffe : Animal {}
...
Animal animal = new Giraffe();
Animalのインスタンスがすぐそこにあります。抽象クラスをインスタンス化するには、それから派生した具体的なクラスを作成し、それをインスタンス化します。派生した具象クラスのインスタンスは、also抽象基底クラスのインスタンスであることを忘れないでくださいAnimalが抽象的であっても、GiraffeのインスタンスはAnimalのインスタンスでもあります。
抽象クラスをインスタンス化できることを考えると、その不変条件が満たされることを保証するために、他のクラスのようなコンストラクターが必要です。
さて、staticクラスは実際にはインスタンス化できないクラスであり、静的クラスでインスタンスコンストラクターを作成することは違法であることに気付くでしょう。 。
これは、抽象クラスの不変式のセットを強制する方法です。つまり、サブクラスが何をしていても、いくつかの事柄が基本クラスに常に当てはまることを確認したい...例:
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
演算子で呼び出すことです。
抽象クラスのすべての実装、または抽象クラスに実装したメソッドに必要な初期化ロジックを強制するためにあります(抽象クラスのすべてのメソッドが抽象である必要はなく、実装できるメソッドもあります)。
抽象基本クラスを継承するクラスは、基本コンストラクターを呼び出す必要があります。
通常、コンストラクターには、作成されるオブジェクトのメンバーの初期化が含まれます。継承の概念では、通常、継承階層の各クラスコンストラクターは、独自のメンバー変数をインスタンス化します。変数が定義されている場所でインスタンス化を行う必要があるため、これは理にかなっています。
抽象クラスは(インターフェイスとは異なり)完全に抽象ではないため、抽象メンバーと具象メンバーの両方が混在しているため、抽象クラスのコンストラクターで行われる抽象でないメンバーを初期化する必要があるため、コンストラクターが必要です抽象クラス。もちろん、抽象クラスのコンストラクターは、派生クラスのコンストラクターからのみ呼び出すことができます。
継承可能な具象クラスThing
のパブリックまたは内部ストレージクラスでコンストラクターを定義すると、2つのメソッドが効果的に定義されます。
InitializeThing
に作用し、戻り値がなく、this
のThing
およびCreateThing
メソッド、およびサブクラスのInitializeThing
メソッドからのみ呼び出すことができるメソッド(InitializeXXX
を呼び出します)。
メソッド(私はCreateThing
と呼びます)は、コンストラクターの指定された型のオブジェクトを返し、基本的に次のように動作します:
Thing CreateThing(int whatever)
{
Thing result = AllocateObject<Thing>();
Thing.initializeThing(whatever);
}
抽象クラスは、最初の形式のメソッドのみを効率的に作成します。概念的には、上記の2つの「メソッド」が同じアクセス指定子を持つ必要がある理由はありません。ただし、実際には、アクセシビリティを異なる方法で指定する方法はありません。実際の実装に関しては、少なくとも.NETでは、CreateThing
は実際には呼び出し可能なメソッドとして実装されているのではなく、newThing = new Thing(23);
ステートメントで挿入されるコードシーケンスを表していることに注意してください。
抽象クラスには、初期化が必要なメンバー変数を含めることができます。したがって、抽象クラスコンストラクターで初期化でき、派生クラスオブジェクトが初期化されると、このコンストラクターが呼び出されます。
から https://msdn.Microsoft.com/en-us/library/ms182126.aspx
抽象型のコンストラクターは、派生型によってのみ呼び出すことができます。パブリックコンストラクターは型のインスタンスを作成し、抽象型のインスタンスを作成できないため、パブリックコンストラクターを持つ抽象型は誤って設計されています。
派生クラスのみが抽象クラスコンストラクターを使用できるため、必要に応じて抽象クラスコンストラクターをprotected
として宣言する必要があります。
ただし、抽象クラスでパブリックコンストラクターを宣言する場合、VSコンパイラーは(デフォルトルールで)文句を言いませんが、新しいインスタンスの作成は許可しません。
私も抽象的な表面に輝きを与えたいと思っています。すべての答えはほぼすべてをカバーしています。それでも私の2セント
抽象クラスは通常のクラスですが、いくつかの例外があります
あなたは絶対に正しいです。抽象メソッドには本体がないため、抽象クラスをインスタンス化できません。つまり、抽象メソッドの実装は不可能です。ただし、基本クラスの変数を初期化するシナリオがいくつかある場合があります。 @Rodrickが提案するbaseキーワードを使用して、これを行うことができます。このような場合、抽象クラスでコンストラクターを使用する必要があります。
すべてのメソッドを実装した後、インスタンス化できます。次に、コンストラクターが呼び出されます。