サブクラスはスーパークラスのメンバを継承することができますが、状況によってはスーパークラスの処理の内容を変更しなくてはならない場合があります。サブクラス側で同じメソッド名でかつ、同じシグネチャ(引数の構成)のメソッドを再び定義することができます。これをメソッドのオーバーライド(override)と呼びます。
例えば、Carクラスでは、スピードの制限がありません。基本的に無限にスピードが出るように設計されています。しかし、Busではスピードの制限を設けないと危険なので、速度の制限を設けたいと思います。
では、Busクラスの定義を修正してみましょう。オーバーライドするためには、スーパークラス側と、サブクラス側でオーバーライドの指定をしなくてはなりません。
○ プロジェクト
プロジェクトを作成して確認してみましょう。
プロジェクトの種類 | コンソール アプリケーション |
---|---|
プロジェクト名 | OverrideTest |
○ 作成の準備
Busクラスにメソッドを追加しましょう。「InheritanceTest」をコピーしてプロジェクトを作成してください。
○ プログラム
まず、CarクラスのSpeedUpメソッドにvirtualキーワードを追加します。
Car.cs
○ 解説
55行目のメソッドの定義でvirtualキーワードを追加しました。これにより、Carクラスを継承したクラスでSpeedUpメソッドをオーバーライドできるようになります。
○ プログラム
次に、BusクラスにSpeedUpメソッドを追加します。
Bus.cs
○ クラス図
○ 解説
68~74行目でoverrideキーワードを指定してSpeedUpメソッドを再定義しています。このメソッドは加速後のスピードが60km/h以下ならスーパークラスであるCarクラスのSpeedUpメソッドを呼び出して加速しています。baseキーワードはスーパークラスを指すので、base.XXと指定することでスーパークラスのメンバを指定することができます。
プログラムの修正はこれで終了です。Busクラスを利用するプログラムは修正をしませんが、60km/hまでしかスピードが出ないようになっています。これは実際のバスの運転手がバスのアクセルを踏むと自動的に60kmまでしかスピードが出なくなる状況と似ています。もしオーバーライドができないと次のようにメソッドを用意することになるかもしれません。
上の図の例だとBusクラスを利用する側では「SpeedUp」と「SpeedUpForBus」というメソッドのどちらを呼び出すかを選択することになります。実際のバスの例だと、無限にスピードが出るアクセルと、60kmまでしかスピードが出ないアクセルが2つ並んでいる状態ということができます。バスの操作説明書には、「アクセルは2つありますが、必ず60㎞/hまでしかスピードが出ないアクセルを踏むようにしてください」とあったとしても、操作ミスで無限にスピードが出るアクセルを踏んでしまうかもしれませんし、スピード狂の運転手であれば、リミッターのかからない(無限にスピードが出る)アクセルをあえて踏むかもしれません。
オーバーライドで「SpeeUp」メソッドを再定義することにより、実際のバスでアクセルは1つあるという状態を作り出すことができます。これにより、バスを安全に運用してもらうことが可能になりますし、運転手を再教育する必要はなくなるということになります。それは、使用している部品がバージョンアップしても、使い方は変わらない(プログラムを変更しなくてもよい)ということになります。