クラスを継承する

チャーシューメンを作ることを考える.チャーシューメンは,ラーメンとの共通点が非常に多い.ラーメンのクラスを引き継ぐことができれば,チャーシューを載せるだけで済みそうである.Ramenクラスに含まれるフィールドとメソッドを図で表してみると,以下のようになる.


これをクラスで表現すると,以下のようになる.先に示した「共通するクラス」のRamenクラスである.

public class Ramen
{
    private int katasa;//1:固い,2:普通,3:柔い
    private int ryou;//1-10
    private Taste soup;
    Ramen()
    {
        System.out.println("ラーメンつくるよ");
    }
    public void setMen(int ryou)
    {
        this.ryou = ryou;
        System.out.println("量:" + ryou);
    }
    public void setKatasa(int katasa)
    {
        this.katasa = katasa;
        System.out.println("固さ:" + katasa);
    }
    public void setSoup(Taste taste)
    {
        this.soup = taste;
        System.out.println("スープ:" + this.soup);
    }
    public void checkRamen()
    {
        System.out.print("量:" + ryou);
        System.out.print("固さ:" + katasa);
        System.out.println("スープ:" + soup);
    }
}

Ramenクラスをもとに,さらに追加としてチャーシューをフィールドとしてもつChashuMenクラスを考える.ChashuMenクラスでは,チャーシューを持つことができるので,そのチャーシューをセットするsetChashuクラスが必要である. Ramenクラスがすでに持っているフィールドとメソッドを踏まえて,ChashuMenクラスで新たに追加したいフィールドとメソッドを図で表すと,以下のようになる.


これをクラスで表すと,以下のようになる.

public class ChashuMen extends Ramen
{
  private int chashu;
  ChashuMen()
  {
  }
  public void setChashu(int chashu)
  {
    this.chashu = chashu;
    System.out.println("チャーシュー:" + chashu);
  }
}

この,Ramenクラスを引き継いで,新しいChashuMenクラスを作るような関係のことを「継承」とよび,プログラム上にて継承するためには「extends」キーワードを用いる.継承する状態を表わすとき,領域を示すようなポンチ絵でなく,一般に使える図表現があり,UML(Unified Modeling Language)と呼ばれる.UMLのクラス図を用いて表わすと,以下の図のようになる.


このような継承の関係があるとき,RamenクラスはChashuMenクラスのスーパークラス,ChashuMenクラスはRamenクラスのサブクラスである.


Javaでは,クラスが継承できるのは1つのクラスだけである.したがって,あるクラスに対するスーパークラスは1つしかない.一方,ある1つのクラスを継承するクラスが複数存在できる.例えば,ClassB1,ClassB2,ClassB3がClassAを継承することは可能である.すなわち,ClassAは複数のサブクラスを持つことができる.


なお,Javaでは,Objcetクラスを頂点とする継承階層を形成する.

MainクラスでChashuMenクラスをインスタンス化して,メソッドを操作して実行する.ChashuMenクラスで定義していないsetMenメソッドなどを実行できる.これは,Ramenクラスを継承しているので,アクセス範囲に制限がなければ,スーパークラスのメソッドとフィールドにアクセスできる.

public class Main
{
    public static void main(String[] args)
    {
        //ラーメンくれ
        System.out.println("===ラーメン===");
        Ramen ramen1 = new Ramen();
        ramen1.setMen(5);
        ramen1.setKatasa(2);
        ramen1.setSoup(Taste.しょうゆ);
        ramen1.checkRamen();
        //固めん10盛りのみそラーメンくれ
        System.out.println("===固めん,10盛り,みそ===");
        Ramen ramen2 = new Ramen();
        ramen2.setKatasa(1);
        ramen2.setMen(10);
        ramen2.setSoup(Taste.みそ);
        ramen2.checkRamen();
        //チャーシューメン
        System.out.println("===普通のチャーシューメン===");
        ChashuMen chashuMen = new ChashuMen();
        chashuMen.setMen(5);
        chashuMen.setKatasa(2);
        chashuMen.setChashu(5);
        chashuMen.setSoup(Taste.みそ);
        chashuMen.checkRamen();
    }
}
===普通のチャーシューメン===
ラーメンつくるよ
量:5
固さ:2
チャーシュー:5
スープ:みそ
量:5固さ:2スープ:みそ

サブクラスの継承

サブクラスを継承して新たなクラスを定義することもできる.


上記のような継承関係を持つクラスで,ラーメンクラス,しょうゆラーメンクラス,チャーシューメンクラスを定義すると,以下のようになる.
class ラーメン
{
(略)
}
class しょうゆラーメン extends ラーメン
{
(略)
}
class チャーシューメン extends しょうゆラーメン
{
(略)
}

演習

Ramenクラスを継承して,タンメンクラスを作成する.タンメンは塩味なので,「しお」が選べるように,Tasteに追加する.また,タンメンは野菜を具として持つので,yasaiフィールドを追加し,yasaiの量を1-3の間で設定できるように,メソッドを作る.
作成したTanmenクラスをインスタンス化して,ふさわしいタンメンが複数できることを確認する.複数のタンメンは,固さや量などが異なる内容とすること.

共通するクラスを継承する