オーバーライドとポリモーフィズム
オーバーライドは、基底クラスで定義されたメソッドの動作を派生クラスで上書きする仕組みです。ポリモーフィズムは、基底クラス型の変数を通じてメソッドを呼んだとき、実体の型のメソッドが実行される性質です。
学習目標
virtual メソッドが派生クラスでオーバーライド可能であることを説明できる
override でメソッドを上書きできる
- 基底クラス型の変数から派生クラスの実装が呼ばれる仕組み(動的ディスパッチ)を説明できる
sealed で継承・オーバーライドを禁止できる
前提知識
1. virtual メソッド
書式:virtual メソッドの定義
1
2
3
| アクセス修飾子 virtual 戻り値の型 メソッド名(引数リスト)
{
}
|
| 要素 |
説明 |
virtual |
派生クラスでオーバーライドを許可することを示すキーワード |
virtual を付けたメソッドは、派生クラスで override できます。virtual を付けないメソッドはオーバーライドできません。
1
2
3
4
| class A
{
public virtual void M() { Console.WriteLine("A.M"); }
}
|
書式:override メソッドの定義
1
2
3
| アクセス修飾子 override 戻り値の型 メソッド名(引数リスト)
{
}
|
| 要素 |
説明 |
override |
基底クラスの virtual メソッドを上書きすることを示すキーワード |
override するメソッドのシグネチャ(名前・戻り値型・引数の型)は基底クラスのものと一致させます。
1
2
3
4
5
6
7
8
9
| class A
{
public virtual void M() { Console.WriteLine("A.M"); }
}
class B : A
{
public override void M() { Console.WriteLine("B.M"); }
}
|
3. ポリモーフィズム(動的ディスパッチ)
基底クラス型の変数に派生クラスのインスタンスを代入してメソッドを呼ぶと、実体の型のメソッドが実行されます。これを動的ディスパッチと呼びます。
1
2
3
4
5
6
7
8
9
10
11
12
| class A
{
public virtual void M() { Console.WriteLine("A.M"); }
}
class B : A
{
public override void M() { Console.WriteLine("B.M"); }
}
A x = new B();
x.M();
|
変数の型が A であっても、実体が B であれば B.M() が呼ばれます。
よくあるミス
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| class A
{
public void M() { } // ❌ virtual がない
}
class B : A
{
public override void M() { } // ❌ コンパイルエラー: A.M() はオーバーライドできない
}
// ✅ OK
class A
{
public virtual void M() { Console.WriteLine("A.M"); }
}
class B : A
{
public override void M() { Console.WriteLine("B.M"); }
}
|
まとめ
virtual はオーバーライドを許可するキーワード
override は基底クラスの virtual メソッドを上書きするキーワード
- 動的ディスパッチ:基底クラス型の変数から呼んでも実体の型のメソッドが実行される
理解度チェック
virtual のないメソッドを派生クラスで override しようとするとどうなりますか?
-
次のコードで x.M() を呼んだとき、A.M() と B.M() のどちらが実行されますか?
1
2
3
4
5
| class A { public virtual void M() { Console.WriteLine("A.M"); } }
class B : A { public override void M() { Console.WriteLine("B.M"); } }
A x = new B();
x.M();
|
解答を見る
- コンパイルエラーになります。
virtual のないメソッドはオーバーライドできません。
B.M() が実行されます。変数の型は A ですが実体が B なので、動的ディスパッチによって B.M() が呼ばれます。
次のステップ
メソッドの隠ぺいと sealed では、new 修飾子による隠ぺいと sealed による拡張の制限を学びます。