可能性のある複製:
抽象C#クラスで抽象コンストラクターを作成できないのはなぜですか?
次のように抽象クラスをクラスのコンストラクターとして宣言できない理由:
public abstract class MyClass {
public abstract MyClass(int param);
}
コンストラクターは、定義されているクラスにのみ適用できます。つまり、コンストラクターは継承されません。基本クラスコンストラクターが使用されます(既定のコンストラクターを自動的に呼び出す場合でも、いずれかを呼び出す必要があります)が、派生クラスによってオーバーライドされることはありません。抽象基本クラスでコンストラクターを定義できます。直接使用することはできませんが、クラスを派生させることで呼び出すことができます。できないことは、派生クラスに特定のコンストラクター署名を強制的に実装させることです。
すべての派生クラスに共通のセットアップコードを定義するために、通常は保護されたコンストラクターを定義することは完全に合理的です。これは、おそらく、抽象クラスがこの設定に依存する他のデフォルト動作を提供する場合に特に当てはまります。例えば:
public abstract class Foo
{
public string Name { get; private set; }
protected Foo( string name )
{
this.Name = name;
}
}
public class Bar : Foo
{
public Bar() : base("bar")
{
...
}
}
abstract
を宣言することはできませんが、抽象クラスにコンストラクターを持つことはできます。 Word abstract
を削除して、その本文を提供するだけです。
コンストラクタは、「通常の」メソッドではなく、静的メソッドに近いものです。静的メソッドと同様に、overloadedにすることはできますが、overridenにすることはできません。つまり、それらは継承されませんが、再定義できます。
public BaseClass
{
public BaseClass( String s ) { ... }
public static void doIt ( String s ) { ... }
}
public SubClass extends BaseClass
{
public SubClass( String s ) { ... }
public static void doIt ( String s ) { ... }
}
public SubClass2 extends BaseClass
{
}
new SubClass( "hello" );
SubClass.doIt( "hello" );
new SubClass2( "hello" ); // NOK
SubClass2.doIt( "hello" ); // NOK
コンストラクタと静的メソッドは決して動的にディスパッチされることはありません(事実上)-インスタンス化する具体的な型または静的メソッドの具体的なクラスを常に知っています。 抽象的なコンストラクターと抽象的な静的メソッドを持つことは意味をなさない理由です。そのため、interfacesでコンストラクターと静的メソッドを指定することもできません。
コンストラクターをstatic factory methodと考えることもできます(そして 対応するパターン を参照してください):
MyClass obj = new MyClass(); // the way it is
MyClass obj = MyClass.new(); // think of it like this
reflectionが使用されている場合は、抽象コンストラクターまたは抽象静的メソッドを定義するのが理にかなっている唯一のケースです。この場合、すべてのサブクラスが対応する静的メソッドまたはコンストラクターを再定義することを保証できます。しかし、反射は別のトピックです...
注:クラスが通常のオブジェクトであるSmalltalkなどの言語では、静的メソッドをオーバーライドし、抽象コンストラクターを持つことができます。ただし、Javaには適用されません。クラスがリフレクションで取得できたとしても、クラスは「通常の」オブジェクトではないためです。
抽象は仮想を意味します。デフォルト以外のコンストラクターをポリモーフィックに呼び出すことはできないため、コンストラクターで仮想および抽象を使用することはできません。
C#の将来のバージョンでは、ジェネリックが拡張され、ジェネリック型パラメーターを介して既定以外のコンストラクターを呼び出すことができるようになります。その後、コンストラクターへの多態的な呼び出しが可能になり、仮想および抽象コンストラクターも追加される可能性があります。
これの何が悪いのか:
public abstract class MyClass {
protected MyClass(int param)
{
}
}
この場合、すべての派生クラスで基本クラスコンストラクターを呼び出す必要があります。
抽象コンストラクターはサポートされていないためです。
ただし、抽象クラスにはコンストラクタを含めることができます。
コンストラクターは通常のメソッドではありません。特別な目的があるため、その目的に合った言語機能に制限されています。参照: なぜコンストラクタは値を返さないのですか?
定義により、クラスを直接インスタンス化することはできないため、ある意味ではすでにクラスは抽象化されています。