tags: [C#入門, Unity, オブジェクト指向]
【C# 入門】virtual と override で「上書き」を使いこなす — 継承の核心を車クラスで理解する
「親クラスのメソッドって、子クラスで書き直せるの?」— その答えが virtual と override です。Unity の MonoBehaviour を使っていれば、実は毎日使っている仕組みです。
まず「継承」をおさらい
C# では、あるクラスを元に別のクラスを作ることができます。これを 継承 と呼びます。
今回の例では Car(車)クラスを親とし、SportCar(スポーツカー)クラスが継承します。
コードを読む前に:3つのキーワード
| キーワード | 内容 |
|---|---|
| KEYWORD 01 | abstract クラスを「設計図専用」にする。new で直接インスタンス化できない。 |
| KEYWORD 02 | virtual 「子クラスで上書きしてもいいよ」という許可マーク。 |
| KEYWORD 03 | override 子クラスが親の virtual メソッドを実際に上書きするときに付ける。 |
| BONUS | base.メソッド() 上書きした後でも、親の処理を呼び出したいときに使う。 |
親クラス Car を作る
abstract を付けると、このクラスは「直接 new Car() できない設計図」になります。
// abstract クラスは new Car() できない「設計図」
public abstract class Car
{
// virtual をつけると子クラスで override(上書き)可能
public virtual void Run()
{
Debug.Log("走るよ!");
}
// virtual がないので子クラスで上書きできない
public void Stop()
{
Debug.Log("止まるよ");
}
}📌 ポイント: Stop() には virtual がありません。これは「この処理は子クラスで変えなくていい」という設計上の意図です。
子クラス SportCar で Run() を上書きする
public class SportCar : Car // Car クラスを継承
{
public override void Run() // Run() を上書き
{
Debug.Log("超速く走るよ!");
base.Run(); // 親の Run() も呼ぶ →「走るよ!」も出力
}
}📌 base.Run() とは? 「上書きした上で、親の処理も実行したい」ときに使います。base は「親クラス」を指します。省略すると親の Run() は呼ばれません。
実際に動かしてみる
Unity で動かすには、MonoBehaviour を継承したスクリプトを作り、空の GameObject にアタッチします。
using UnityEngine;
public class CarTest : MonoBehaviour
{
void Start()
{
SportCar sportCar = new SportCar();
sportCar.Run(); // SportCar の Run() が呼ばれる
sportCar.Stop(); // Car の Stop() がそのまま使われる
}
}手順
Car.cs・SportCar.cs・CarTest.csの3ファイルを Assets に作成- 空の GameObject を作成し、
CarTestをアタッチ - Play ボタンを押すと Console に出力される
Console 出力:
超速く走るよ!
走るよ!
止まるよ⚠️ なぜ「超速く走るよ!」の後に「走るよ!」が出るの?
base.Run()を書いているため、上書きした処理の後に親の処理も実行されます。base.Run()を消すと「超速く走るよ!」だけになります。
virtual と override の対応関係を整理
| キーワード | どこに書く | 意味 |
|---|---|---|
| virtual | 親クラスのメソッド | 「子クラスで上書きしてよい」と宣言する |
| override | 子クラスのメソッド | 親の virtual メソッドを実際に上書きする |
| base.〇〇() | override したメソッド内 | 上書きしつつ親の処理も呼び出す |
| abstract | クラス or メソッド | 直接インスタンス化・実装を禁止し、継承を強制する |
Unity との繋がり:実は毎日使っている
MonoBehaviour の Start() や Update() を使ったことがありますよね?
あれはまさに Unity が用意した virtual メソッドを、あなたが override している仕組みです(Unity では省略記法が使われていますが、内部は同じです)。
public class MyScript : MonoBehaviour
{
// MonoBehaviour の virtual void Start() を override している
void Start() { }
// MonoBehaviour の virtual void Update() を override している
void Update() { }
}📌 つまり: virtual / override を理解することは、Unity の動作原理を理解することに直結しています。
まとめ
virtual は「上書きしてもいいよ」という親からの許可。override は子クラスがその許可を使って実際に上書きすること。base.メソッド() で親の処理も併用できる。abstract はクラスを設計図専用にして直接 new できなくする仕組みです。
この4つを押さえると、複数の車種(Truck、Busなど)を同じ Car 型で扱いつつ、Run() の挙動だけ個別に変える — いわゆる ポリモーフィズム の入口まで、一気に見えてきます。