継承

 継承は、インヘリタンスとも呼ばれます。既に用意されているオブジェクトを基に、機能などを追加して新たなオブジェクトを作ることができる機能です。

 これから、Busクラスを作成してみましょう。バスは、人を乗せて運ぶことができますが、車と同じように進んだり、止まったりすることができます。つまり、Carクラスのような機能を持っています。「バスは車である」ということができます。このような関係を「is-a」の関係といいます(Bus is a Car)。

 このような場合、BusクラスはCarクラスの機能等を引き継いで作成することができます。Carクラスを継承してBusクラスを作ることができます。このようにすることで、Busにしかない属性、機能を記述すればよくなります。つまり、CarクラスとBusクラスの差分を記述するわけです。

 継承において、もとになるクラスをスーパークラスや基底クラスといい、それをもとに新しく作成するクラスをサブクラスや派生クラスといいます。

クラス継承の書式
class サブクラス名 extends スーパークラス名{
 各種定義…
}

 継承の指定をした後、スーパークラスにはないフィールドやメソッドを追加や修正する記述をします。

○ ファイル

 次のようにファイルを作成してください。

ファイル名 Bus.java

サンプルダウンロード

○ プログラム

 Busクラスを追加して、次のように記述してください。

  1. class Bus extends Car{
  2.  //フィールド==========
  3.  private int salesAmount;     //運賃
  4.  private int passengerNumber;     //乗客人数
  5.  //コンストラクタ==========
  6.  public Bus(){
  7.   this(100);
  8.  }
  9.  public Bus(double gas){
  10.   super(gas);
  11.   this.salesAmount = 0;
  12.   this.passengerNumber = 0;
  13.  }
  14.  //メソッド==========
  15.  //乗車させるメソッド
  16.  public String rideToBus(int fare){
  17.   //走行中かどうか
  18.   if(this.getSpeed() != 0){
  19.    return "停車してください。";
  20.   }
  21.   //満席かどうか
  22.   if(this.passengerNumber >= 50){
  23.    return "満席のため、乗車できません。";
  24.   }
  25.   //料金と、乗車人数を加算
  26.   this.salesAmount += fare;
  27.   this.passengerNumber++;
  28.   return null;
  29.  }
  30.  //降車させるメソッド
  31.  public String getOffBus(){
  32.   //走行中かどうか
  33.   if(this.getSpeed() != 0){
  34.    return "停車してください。";
  35.   }
  36.   //乗客がいるかどうか
  37.   if(this.passengerNumber == 0){
  38.    return "乗客はいません。";
  39.   }
  40.   //乗車人数を減算
  41.   this.passengerNumber--;
  42.    return null;
  43.  }
  44.  //フィールドのgetterの準備
  45.  public int getSalesAmount(){
  46.   return this.salesAmount;
  47.  }
  48.  public int getPassengerNumber(){
  49.   return this.passengerNumber;
  50.  }
  51. }

○ クラス図

○ 解説

 1行目でCarクラスを継承しています。これにより、Carクラスが持っているspeedUpメソッド、speedDownメソッドが使えるようになります。

 3行目のフィールド変数は売上金額を扱います。乗客が乗車するたびに加算されていきます。このフィールドはprivate修飾子がついているので、設定はクラス内部からしかできないようになっています。値を取得するには54行目から定義されているgetSalesAmount()メソッドを利用します。4行目のフィールド変数は現在の乗客数を扱います。今回は50人まで乗せられるようにプログラムで制御しています。このフィールドも設定はクラス内部からしかできないようになっています。取得するには58行目から定義されているgetPassengerNumber()メソッドを利用します。

 7~9行目ではコンストラクタを定義しています。このコンストラクタは引数なしで呼ばれると、オーバーロードしているガソリン量を受け取るコンストラクタを呼び出します。11~15行目では、ガソリン量を受け取るコンストラクタを定義しています。12行目はスーパークラスのコンストラクタを呼び出しています。「super」キーワードは、スーパークラスを表します。ここでのsuperキーワードはCarクラスを表します。

 19~34行目は乗車するメソッドです。このメソッドは運賃を受け取り、乗車処理をします。その際、バスが走っていたり、乗客数が満員になっていたりすると乗車できないようにしています。いずれにも当てはまらない場合は、受け取った運賃を売上金額フィールドに加算し、乗客数フィールドを1人分増やします。

 37~51行目は降車するメソッドです。バスが走っていたり、乗客がいない場合は降車できないようにしています。いずれにも当てはまらない場合は、乗客数フィールドを1人分減らします。 

○ ファイル

 Run1.javaをコピーして、次のようにファイルを作成してください。

ファイル名 Run2.java

○ プログラム

 次のようにプログラムを記述してください。

  1. public class Run2{
  2.  //車の状態を表示するメソッド
  3.  public static void showData(Bus bus){
  4.   System.out.println("スピード:" + bus.getSpeed() + "km");
  5.   System.out.println("ガソリン:" + bus.getGas() + "L");
  6.   System.out.println("売上金額:" + bus.getSalesAmount() + "円");
  7.   System.out.println("乗車人数:" + bus.getPassengerNumber() + "人");
  8.  }
  9.  public static void main(String[] args) throws Exception{
  10.   //インスタンスを生成する
  11.   Bus bus = new Bus(150);
  12.   //現在の状態を表示する
  13.   showData(bus);
  14.   //キーボード入力の準備をする
  15.   BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  16.   while(true){
  17.    //操作を入力
  18.    System.out.print("1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:");
  19.    String inputdata = br.readLine();
  20.    //操作によって分岐する
  21.    switch (inputdata){
  22.     case "1":
  23.      //加速する
  24.      bus.speedUp(5);
  25.      showData(bus);
  26.      break;
  27.    case "2":
  28.      //減速する
  29.      bus.speedDown(5);
  30.      showData(bus);
  31.      break;
  32.     case "3":
  33.     //給油する
  34.      bus.setGas(80);
  35.      showData(bus);
  36.      break;
  37.     case "7":
  38.      //乗車する
  39.     String retgetoff = bus.rideToBus(200);
  40.      if(retgetoff == null){
  41.       showData(bus);
  42.      }else{
  43.       System.out.println(retgetoff);
  44.      }
  45.      break;
  46.     case "8":
  47.      //降車する
  48.      String retride = bus.getOffBus();
  49.      if(retride == null){
  50.       showData(bus);
  51.      }else{
  52.       System.out.println(retride);
  53.      }
  54.      break;
  55.     case "9":
  56.      //プログラムを終了する
  57.      return;
  58.    }
  59.   }
  60.  }
  61. }

○ 解説

 14行目でBusオブジェクトを生成しています。BusオブジェクトはCarクラスを継承しているので今まで通り加速したり、減速したりできます。46行目では乗車メソッドを呼び出しています。戻り値がnullでない場合はエラーメッセージが返って来ているので、コンソールに表示しています。55行目では降車メソッドを呼び出しています。このメソッドは乗車メソッドと同様にエラーメッセージかnullが返ってくるのでそれに応じた処理をしています。

 今回はCarクラスを基にBusクラスを作成しました。BusクラスはCarクラスを継承しているので、Carクラスのメンバを記述しなくても使用することができます。ただし、privateになっているメンバは、継承したクラスでも直接アクセスすることができません。「protected」にすれば、直接操作できます。「protected」は、継承関係であればアクセスできますが、外部クラスからはアクセスすることができません。

 Javaでは、サブクラスは1つのクラスから継承することができます。複数のクラスから継承させることはできません。(多重継承の禁止)

Busクラスのイメージ
Busクラスのイメージ

 Busクラスのインスタンスを生成するときにBusクラスのコンストラクタを呼び出します。すると、初めにスーパークラスであるCarクラスのコンストラクタを呼び出します。サブクラスのコンストラクタでスーパークラスのコンストラクタの呼び出しが特に記述されていない場合、スーパークラスのデフォルトコンストラクタが呼び出されます。もし、スーパークラスで引数を持つコンストラクタが定義されていると、デフォルトコンストラクタは仮定されないので、サブクラスでスーパークラスのコンストラクタの呼び出しを記述しなければなりません。

インスタンス生成の手順
インスタンス生成の手順

前へ   次へ