基本クラスA
と、B
から派生したクラスA
があるとします。次に、クラスA
のコンストラクターがクラスB
に継承されることはありません。ただし、B
の新しいオブジェクトが作成されると、クラスA
のデフォルト/カスタムコンストラクターが呼び出される前に、クラスB
のデフォルトコンストラクターが呼び出されます。たぶんこれの目的は、クラスA
のフィールドをデフォルト値に初期化する必要があることです。
ここで、クラスA
がカスタムコンストラクターを定義したとします。これは、クラスA
のデフォルトコンストラクターがコンパイラによって暗黙的に削除されることを意味します。さて、クラスB
の新しいインスタンスを作成すると、クラスA
のコンストラクターを呼び出す前に、クラスB
のどのコンストラクターが自動的に呼び出されますか? (このような場合、クラスA
フィールドはどのように初期化されますか?)
さて、クラス
B
の新しいインスタンスを作成すると、クラスA
コンストラクターを呼び出す前に、クラスB
のどのコンストラクターが自動的に呼び出されますか?
基本的に、コードはコンパイルに失敗します。各コンストラクターは、暗黙的または明示的に別のコンストラクターにチェーンする必要があります。チェーンするコンストラクターは、同じクラス(this
を使用)または基本クラス(base
を使用)に含めることができます。
このようなコンストラクタ:
_public B() {}
_
暗黙的に:
_public B() : base() {}
_
...そして、コンストラクタをまったく指定しない場合、同じ方法で暗黙的に追加されますが、それでも何か呼び出す必要があります。たとえば、あなたのシナリオ:
_public class A
{
public A(int x) {}
}
public class B : A {}
_
次のコンパイラエラーが発生します。
エラーCS7036:必要な仮パラメータ_
'x'
_ of'A.A(int)'
に対応する引数が指定されていません
ただし、別のコンストラクター呼び出しを明示的に指定できます。
_public B() : base(10) {} // Chain to base class constructor
_
または
_public B() : this(10) {} // Chain to same class constructor, assuming one exists
_
コンストラクターの実行が完了すると、オブジェクトは有効な初期状態にあります有効なオブジェクトを使用することになります。
クラスAにデフォルト以外のコンストラクターを提供する場合-事実上、クラスAオブジェクトを構築するには、つまり有効な初期状態にするには-パラメーターによって提供される、より多くの情報が必要です。
これを考えると、コンパイラーはnotによってデフォルトのコンストラクターを生成します。クライアントコードはコンパイルに失敗します(必要な場合-オブジェクトを有効な状態にする方法は他にありますか?)-クライアントプログラマーは座って注意する必要があります。
明示的な空のコンストラクターを提供する場合-コンパイラーに効果的に伝えている-私は何をしているのかを知っています-デフォルトのコンストラクターはおそらくフィールドを適切なデフォルト値に初期化するでしょう。
または再利用を促進するために-デフォルトのコンストラクターは、いくつかのデフォルト値を使用してデフォルト以外のコンストラクターを呼び出すことができます。
サブクラスはそのスーパークラスを知っています-サブクラスのコンストラクターはスーパークラスのメソッドを呼び出すことができます(サブクラスで一般的に再利用されるメソッド)。上記を考えると、スーパークラス部分は有効な状態-つまり、メソッド呼び出しの前にコンストラクターが実行されたである必要があります。これには、サブクラスコンストラクターの前にスーパーコンストラクターを呼び出す必要があります。
これを考えると、正しい初期状態の動作を実施するようにコンストラクターを簡単に設計できます。