オーバーライド

 サブクラスはスーパークラスのメンバを継承することができますが、状況によってはスーパークラスの処理の内容を変更しなくてはならない場合があります。サブクラス側で同じメソッド名でかつ、同じシグネチャ(引数の構成)のメソッドを再び定義することができます。これをメソッドのオーバーライド(override)と呼びます。

 例えば、Carクラスでは、スピードの制限がありません。基本的に無限にスピードが出るように設計されています。しかし、Busではスピードの制限を設けないと危険なので、速度の制限を設けたいと思います。

Busクラスでオーバーライド
Busクラスでオーバーライド

 では、Busクラスの定義を修正してみましょう。オーバーライドするためには、スーパークラス側と、サブクラス側でオーバーライドの指定をしなくてはなりません。

■ オーバーライドされる側

Public Overridable Sub SpeedUp(sp As Integer)
 ・・・
End Sub

■ オーバーライドする側

Public Overrides Sub SpeedUp(sp As Integer)
 ・・・
End Sub

○ プロジェクト

プロジェクトを作成して確認してみましょう。

プロジェクトの種類 コンソール アプリケーション
プロジェクト名 OverrideTest

サンプルダウンロード

○ 作成の準備

 Busクラスにメソッドを追加しましょう。「InheritanceTest」をコピーしてプロジェクトを作成してください。

○ プログラム

 まず、CarクラスのSpeedUpメソッドにvirtualキーワードを追加します。

Car.vb

  1. Public Class Car
  2.  'フィールド==========
  3.  'Public _speed As Integer 'スピード情報
  4.  Private _speed As Integer 'スピード情報(修正)
  5.  'Public _gas As Double 'ガソリン情報
  6.  Private _gas As Double 'ガソリン情報(修正)
  1.  'メソッド==========
  2.  '加速させるメソッド
  3.  Public Overridable Sub SpeedUp(sp As Integer)
  4.   'ガソリンを減らす
  5.   Me._gas -= sp / 10.0
  6.   If Me._gas < 0 Then 'ガソリンがマイナスになる場合
  7.    'ガソリンを0に補正し、スピードを増やさない
  8.    Me._gas = 0
  9.   Else
  10.    'スピードを増やす
  11.    Me._speed += sp
  12.   End If
  13.  End Sub

○ 解説

 42行目のメソッドの定義でOverridableキーワードを追加しました。これにより、Carクラスを継承したクラスでSpeedUpメソッドをオーバーライドできるようになります。

○ プログラム

 次に、BusクラスにSpeedUpメソッドを追加します。

Bus.vb

  1. Public Class Bus
  2.  Inherits Car
  3.  'プロパティ==========
  4.  Public Property SalesAmount As Integer '運賃
  5.  Public Property PassengerNumber As Integer '乗客人数
  6.  'コンストラクタ==========
  7.  Public Sub New()
  8.   Me.New(100)
  9.  End Sub
  10.  Public Sub New(gas As Double)
  11.   MyBase.New(gas)
  12.   Me.SalesAmount = 0
  13.   Me.PassengerNumber = 0
  14.  End Sub
  15.  'メソッド==========
  16.  '乗車させるメソッド
  17.  Public Function RideToBus(fare As Integer) As String
  18.   '走行中かどうか
  19.   If Me.Speed <> 0 Then
  20.    Return "停車してください。"
  21.   End If
  22.   '満席かどうか
  23.   If Me.PassengerNumber >= 50 Then
  24.    Return "満席のため、乗車できません。"
  25.   End If
  26.   '料金と、乗車人数を加算
  27.   Me.SalesAmount += fare
  28.   Me.PassengerNumber += 1
  29.   Return Nothing
  30.  End Function
  31.  '降車させるメソッド
  32.  Public Function GetOffBus() As String
  33.   '走行中かどうか
  34.   If Me.Speed <> 0 Then
  35.    Return "停車してください。"
  36.   End If
  37.   '乗客がいるかどうか
  38.   If Me.PassengerNumber = 0 Then
  39.    Return "乗客はいません。"
  40.   End If
  41.   '乗車人数を減算
  42.   Me.PassengerNumber -= 1
  43.    Return Nothing
  44.  End Function
  45.  '加速させるメソッド(オーバーライド)
  46.  Public Overrides Sub SpeedUp(sp As Integer)
  47.   If (Me.Speed + sp) <= 60 Then
  48.    MyBase.SpeedUp(sp)
  49.   End If
  50.  End Sub
  51. End Class

○ クラス図

○ 解説

 51~55行目でOverridesキーワードを指定してSpeedUpメソッドを再定義しています。このメソッドは加速後のスピードが60km/h以下ならスーパークラスであるCarクラスのSpeedUpメソッドを呼び出して加速しています。MyBaseキーワードはスーパークラスを指すので、MyBase.XXと指定することでスーパークラスのメンバを指定することができます。

 プログラムの修正はこれで終了です。Busクラスを利用するプログラムは修正をしませんが、60km/hまでしかスピードが出ないようになっています。これは実際のバスの運転手がバスのアクセルを踏むと自動的に60kmまでしかスピードが出なくなる状況と似ています。もしオーバーライドができないと次のようにメソッドを用意することになるかもしれません。

オーバーロードを使わないと…
オーバーロードを使わないと…

 上の図の例だとBusクラスを利用する側では「SpeedUp」と「SpeedUpForBus」というメソッドのどちらを呼び出すかを選択することになります。実際のバスの例だと、無限にスピードが出るアクセルと、60kmまでしかスピードが出ないアクセルが2つ並んでいる状態ということができます。バスの操作説明書には、「アクセルは2つありますが、必ず60㎞/hまでしかスピードが出ないアクセルを踏むようにしてください」とあったとしても、操作ミスで無限にスピードが出るアクセルを踏んでしまうかもしれませんし、スピード狂の運転手であれば、リミッターのかからない(無限にスピードが出る)アクセルをあえて踏むかもしれません。

 オーバーライドで「SpeeUp」メソッドを再定義することにより、実際のバスでアクセルは1つあるという状態を作り出すことができます。これにより、バスを安全に運用してもらうことが可能になりますし、運転手を再教育する必要はなくなるということになります。それは、使用している部品がバージョンアップしても、使い方は変わらない(プログラムを変更しなくてもよい)ということになります。

前へ   次へ