継承は、他のクラスの機能をそのまま受け継ぐことができます。
C#では、多重継承をすることが許されていないので注意してください。
継承元のクラスを 基底クラス といい、継承先のクラスを 派生クラス といいます。
public class A // 基底クラス
{
public A() { }
}
public class B : A // 基底クラス A を継承した派生クラス B
{
public B() { }
}
派生クラスは、暗黙的に基底クラスのインスタンスをもつと考えられるため、派生クラスは基底クラスのすべてのメンバにアクセスすることができます。
では、ここで疑問に思うのが基底クラスと派生クラスのメンバ名が同じだった場合、どちらが評価されるのかということです。
このような状態にあるとき、基底クラスの同じメンバは 隠蔽 され、基底クラスのメンバは派生クラスのメンバで書き換えられます。
しかし、これでは派生クラスを見ただけでは何が隠蔽されているのか非常にわかり難いため、
派生クラスで基底クラスのメンバを隠蔽することを明示するために new 演算子を指定します。
public class A
{
public string str = "neko";
}
public class B : A
{
new public string str = "momiji"; // 基底クラスのメンバ変数 str を隠蔽。
public void Show()
{
Console.WriteLine(str);
}
static void Main()
{
B b = new B();
b.Show(); // momiji が出力されます。
}
}
では、隠蔽されたメンバにはどのようにアクセスしたらよいのか疑問に思いますよね。
隠蔽されたメンバにアクセスするには base キーワードを使用します。
base は基底クラスのインスタンスを表します。
public class A
{
public string str = "neko";
}
public class B : A
{
new public string str = "momiji"; // 基底クラスのメンバ変数 str を隠蔽。
public void Show()
{
Console.WriteLine(base.str); // 基底クラスのメンバ変数 str を呼び出します。
}
static void Main()
{
B b = new B();
b.Show(); // neko と出力されます。
}
}
最後に、基底クラスのコンストラクタについて説明します。
引数無しのコンストラクタについては、問題なく実行されるはずです。
何故ならば、コンストラクタを宣言していない場合は自動的に引数無しのコンストラクタが生成されて実行されるからです。
public class A
{
public string str;
public A() // 引数無しコンストラクタ。
{
str = "neko";
}
}
public class B : A
{
new public string str; // 基底クラスのメンバ変数 str を隠蔽。
public B( string str) // 引数ありコンストラクタ。
{
this.str = str;
}
public void Show()
{
Console.WriteLine(base.str); // 基底クラスのメンバ変数 str を呼び出します。
}
static void Main()
{
B b = new B("momiji");
b.Show(); // neko と出力されます。
}
}
しかし、ここで問題になってくるのが基底クラスの引数ありコンストラクタです。
現状ではコンストラクタに引数の渡しようがありませんよね。
これを解決するには、コンストラクタ初期化子 base() を派生クラスのコンストラクタに指定してやります。
public class A
{
public string str;
public A(string str)
{
this.str = str;
}
}
public class B : A
{
new public string str;
public B( string str) : base("neko") // base("neko") は基底クラスのコンストラクタを呼び出します。
{
this.str = str;
}
public void Show()
{
Console.WriteLine(base.str);
}
static void Main()
{
B b = new B("momiji");
b.Show();
}
}
基底クラスのコンストラクタが呼び出されるタイミングですが、派生クラスのコンストラクタが呼び出される前に実行されます。
//サンプル36