web-dev-qa-db-ja.com

コンストラクターのパラメーターと継承

OOPの新機能です。C#の基本クラスから継承するときに、派生クラスコンストラクターがどのように機能するかで混乱しています。

最初に基本クラス:

class BaseClass
{
    private string BaseOutput = null;

    public BaseClass(string BaseString)
    {
        BaseOutput = BaseString;
    }

    public virtual void PrintLine()
    {
        Console.WriteLine(BaseOutput);
    }
}

派生クラスは次のとおりです。

class SubClass : BaseClass
{
    private string SubOutput = null;

    public SubClass(string BaseString, string SubString) : base(BaseString)
    {
        SubOutput = SubString;
    }

    public override void PrintLine()
    {
        Console.WriteLine(SubOutput);
    }
}

最後に、プログラムの主要部分:

class Program
{
    static void Main(string[] args)
    {
        BaseClass theBase = new BaseClass("Text for BaseClass");
        SubClass theSub = new SubClass("2nd param", "Text for SubClass");

        theBase.PrintLine();
        theSub.PrintLine();

        Console.ReadKey();
    }
}

派生クラスのコンストラクターを呼び出すときに、基本クラスが必要とするパラメーターも渡さなければならない理由はわかりません。派生クラスのBaseOutputフィールドに値が割り当てられていない場合、nullに設定したままにしてはいけませんか?なぜこのようなことはできないのですか:

public SubClass(string SubString) : base(BaseString)

さらに、この派生クラスでコンストラクターを呼び出すとき、最初のパラメーターは基本クラスのパラメーターと同じ名前にする必要があります。そうしないと、エラーがスローされます。派生クラスでAnotherStringと呼ばれる新しい文字列変数を定義する場合、なぜこれが機能しないのでしょうか。

public SubClass(string AnotherString, string SubString) : base(BaseString)

最後に、正しい方法でこれを入力すると...

public SubClass(string BaseString, string SubString) : base(BaseString)

... SubClassコンストラクターの最初のパラメーターは何に使用されますか?派生クラスのどのメソッドでも割り当ても使用もされていません。なぜそこに置く必要があるのですか?

21
Frank

できない理由について:

public SubClass(string SubString) : base(BaseString)

BaseStringはどうなりますか?

できること:

public SubClass(string SubString) : base("SomeFixedString")

または

public SubClass(string SubString) : base(SubString)

ただし、1つの文字列を基本クラスコンストラクターのパラメーターに渡し、追加の文字列が必要な場合は、2つのパラメーターを受け入れる必要があります。

同じ名前を保持することに関しては、do n'tです。できること:

public SubClass(string AnotherString, string SubString) : base(AnotherString)

最後の質問については、最初のパラメーターは何もしていません。基本クラスコンストラクターに渡されています。必要に応じて、他の何かに使用できます。

22
Servy

BaseStringを設定しないように派生クラスに機会を提供したい場合は、次のように基本クラスにデフォルトコンストラクターを提供する必要があります。

public BaseClass()
{

}

派生クラスでは、次のように基本クラスの引数なしでコンストラクターを呼び出すことができます。

public SubClass(string AnotherString)
     : base()
{
    // base() => explicit call to default construct in the base class.
    // Do something else
}

これにより、優れたソフトウェアエンジニアリングのプラクティスが提供されます。基本クラスの文字列を設定しない機会を提供する場合は、基本クラスで設定します。ベースコンストラクターに引数としてnullを渡すような他の「ハック」は、サブクラスから行うべきではない方法で、基本クラスの内部をいじるのに役立ちます。

4
ose
public SubClass(string BaseString, string SubString) : base(BaseString)

派生クラスのこのコンストラクターは、2つの引数BaseStringおよびSubStringを受け取ったときに、BaseStringを使用して基本クラスのコンストラクターを呼び出します。

したがって、やって

public SubClass(string a, string b) : base(BaseString)

BaseStringを使用して基本クラスのコンストラクターを呼び出すように指示しているが、BaseStringと呼ばれる引数がないため、機能しません。

文字列を基本クラスコンストラクターに渡さずに派生クラスをインスタンス化する場合、基本クラスにはデフォルトのコンストラクターが必要です。

public BaseClass() { }
2
xbonez

BaseStringをデフォルト値で初期化する場合は、その値を基本クラスコンストラクターに渡します(したがって、そのパラメーターを派生クラスコンストラクターに渡す必要はありません)

public SubClass(string SubString) : base(null)

または、基本クラスでパラメーターなしのコンストラクターを定義します。

また、パラメーターの命名について-派生コンストラクターに渡すパラメーターの名前は関係ありません。重要なのは、ベースコンストラクターに渡す値だけです。

public SubClass(string AnotherString, string SubString) : base(AnotherString)
1