web-dev-qa-db-ja.com

コンストラクターを継承できますか?

C#でコンストラクターを継承することはできませんが、おそらく私がやりたいことを行う方法があります。

他の多くのクラスに継承される基本クラスがあり、1つのパラメーターを取得して初期化を行うInitメソッドがあります。他のすべての継承クラスもこの初期化を必要としますが、次のようなすべてのクラスに対して個別のコンストラクターを作成する必要があります。

public Constructor(Parameter p) {
    base.Init(p);
}

これはDRYの原則に違反します!多数のコンストラクタを作成せずに必要なものをすべて初期化するにはどうすればよいですか?

46
Alex

すべてのコンストラクターを同じコードで作成する必要はありません。作成するのは1つだけですが、派生クラスでベースコンストラクターを呼び出します。

public class Base
{
    public Base(Parameter p)
    {
        Init(p)
    }

    Init(Parameter p)
    {
        // common initialisation code
    }
}

public class Derived : Base
{
    public Derived(Parameter p) : base(p)
    {

    }
}
80
Rob Levine

Init関数を基本クラスのコンストラクターに変更し、次のように継承されたオブジェクトから呼び出します。

public InheritedObject(Parameter p) : base(p)
{
}

基本コンストラクターは、コンストラクター自体のコードが実行される前に呼び出されます。

10
AHM

base.Init呼び出しを繰り返さない唯一の方法は、代わりに基本コンストラクターを呼び出すことです

class Base
{
  public Base(Parameter p)
  {
    this.Init(p)
  }

  private void Init(Parameter p)
  {
      ...
  }
}

class Inherited : Base
{
   public Inherited(Parameter p)
     : base(p)
   {
      // other constructor logic, but Init is already called.
   }
}
7
Jamiec

コンストラクターを継承することはできませんが、派生した子のコンストラクターからコンストラクターを呼び出すことはできます。基本クラスのデフォルトコンストラクタをプライベートにすると、派生クラスを作成するたびに基本コンストラクタを選択するように強制されます。

class A
{
    protected A(int x)
    {

    }
}
class B : A
{
    B(int x)
        : base(x)
    {

    }
}
3
rerun

このようなもの?

public Constructor(Parameter p) : base(p) {

}

そして基本クラス:

public Base(Parameter p)
{
    Init(p);
}

Initメソッドを仮想としてマークすることもできるので、必要に応じて他のクラスで甘いオーバーライドを行うことができます! ;)

public virtual void Init() { }

他のクラスでは:

public override void Init() { base.Init(); //Do other stuff }
2
Arcturus