この章のテーマ §
継承時のvirtualキーワード、overrideキーワードとnewキーワードについて学びます。この2つは異なる効能を持ちます。
前提知識 §
Console.WriteLineメソッド, 文字列の基礎, 変数の基礎, クラスの基礎, メソッドの基礎, new演算子,
解説 §
継承したクラスに、元のクラスと同じ名前のメンバーがあるとエラーになります。これを回避して同じ名前のメソッドを使う方法が2つあります。
一つはnewキーワードを付けて同じ名前の新しいメソッドを記述することを宣言する方法です。
もう一つは、overrideキーワードを付けて同じ名前のメソッドの動作を乗っ取る方法です。
サンプルソースの動作結果を見ると分かる通り、この2つは動作が違います。
後者の方法は、どんな型を経由して呼び出しても乗っ取った方のメソッドが呼ばれます。反面、乗っ取られる予定のあるメソッドにはvirtualキーワードを付けて【乗っ取り可能】を宣言しなければなりません。(newキーワードを使う場合は宣言不要です)
罠の数々 §
- overrideキーワードは、中味のない抽象メンバーに中味を与える時にも使用される。その際は、virtualキーワードではなくabstractキーワードと併用される
- overrideで乗っ取ったメソッドから元のメソッドを呼びたいときがある。その時は、baseキーワードを使ってbase.メソッド名();とすれば良い
- クラスライブラリにもvirtualが追加メソッドは多くある。それらは継承で機能を追加拡張することを意図している
- virtualキーワードを全てのメソッドに付けることはお勧めではない。メモリ消費量も増えるし、どこでどんな機能の差し替えが起こって動作に問題を起こすか分からないためである
参考リンク §
Override キーワードと New キーワードを使用する場合について (C# プログラミング ガイド)
Override キーワードと New キーワードによるバージョン管理 (C# プログラミング ガイド)
サンプルソース: kw_virtual §
Console.WriteLine("BクラスのインスタンスをクラスAから使った時。");
A x = new B();
x.Sub1();
x.Sub2();
Console.WriteLine("BクラスのインスタンスをクラスBから使った時。");
B y = new B();
y.Sub1();
y.Sub2();
public class A
{
public void Sub1()
{
Console.WriteLine("I'M A");
}
public virtual void Sub2()
{
Console.WriteLine("I'M A");
}
}
public class B:A
{
public new void Sub1()
{
Console.WriteLine("I'M B");
}
public override void Sub2()
{
Console.WriteLine("I'M B");
}
}
実行結果 §
BクラスのインスタンスをクラスAから使った時。
I'M A
I'M B
BクラスのインスタンスをクラスBから使った時。
I'M B
I'M B
リポジトリ §
https://github.com/autumn009/CSharpPrimer2
練習問題 §
以下のプログラムの実行結果を予測してみよう。
var x = new MyClass();
Console.WriteLine(x);
public class MyClass
{
public override string? ToString()
{
return $"This is {base.ToString()}";
}
}
- どこにもvirtualキーワードがないのにoverrideキーワードを使ったからコンパイルエラー
- x
- MyClass
- This is MyClass
- This is {base.ToString()}
[[解答]]