はじめに
Java一年未満の方へ研修用
継承・オーバーライドに関して少し掘り下げて紹介
対象
・Java一年未満
継承とは
・あるクラスの状態と動作を別のクラスが引き継ぐことです。
・継承をすることによって、コードの効果的な再利用ができるようになります。
例えば消防車とトラックは両方とも車です。
以下の赤い文字の部分は共通しています。
車クラスをスーパークラスとして実装することで、消防車クラスとトラッククラスの実装が楽になります。
継承の使い方
サブクラスを作成するには「extends」(読み:エクステンズ)を使用する。
次のように「extends」の前にサブクラス名(子クラス名)、後にスーパークラス名(親クラス名)を指定する。
public class BusinessPerson extends Person {
// 処理
}
サブクラス:BusinessPerson
スーパークラス:Person
継承を使うメリット
・同一の処理をスーパークラスにまとめることで修正リスクを軽減できる
・何度も同じ処理を書かなくて済むためソースの可読性が上がる
※ただし、やるすぎると逆に保守性や可読性が落ちる場合があるので、その辺の加減が難しいところ。。
・少しだけ違う処理をサブクラスに実装できる
「車」を例に継承を使う場合と使わない場合を比較してみる。
継承を使わない場合
// トラッククラス
public class Truck {
// 車種
String CAR_NAME = "トラック";
// タイヤ
int tire;
// ハンドル
int handle;
// アクセル
int accelerator;
// ブレーキ
int brake;
// 荷台
int carrier;
public void move() {
System.out.println(CAR_NAME + "が走ります。");
}
public void blinker() {
System.out.println(CAR_NAME + "がウインカーを出します。");
}
public void bring() {
System.out.println(CAR_NAME + "が荷物を運びます。");
}
}
// 消防車クラス
public class FireTruck {
// 車種
String CAR_NAME = "消防車";
// タイヤ
int tire;
// ハンドル
int handle;
// アクセル
int accelerator;
// ブレーキ
int brake;
// ホース
int hose;
public void move() {
System.out.println(CAR_NAME + "が走ります。");
}
public void blinker() {
System.out.println(CAR_NAME + "がウインカーを出します。");
}
public void waterDischarge() {
System.out.println(CAR_NAME + "が放水します。");
}
}
上記2つのクラスは、どちらも車に関連するクラスであり、以下の内容がまったく同じです。
// タイヤ
int tire;
// ハンドル
int handle;
// アクセル
int accelerator;
// ブレーキ
int brake;
public void move() {
System.out.println(CAR_NAME + "が走ります。");
}
public void blinker() {
System.out.println(CAR_NAME + "がウインカーを出します。");
}
同じ内容のソースコードを色々な個所に書くと、修正する際に複数の個所を直す必要があり、可読性・保守性が悪くなる。
継承を使う場合
// 車のスーパークラス
public class Car {
int tire;
int handle;
int accelerator;
int brake;
public void move() {
System.out.println("車が走ります。");
}
public void blinker() {
System.out.println("車がウインカーを出します。");
}
}
// トラッククラス(サブクラス)
public class Truck extends Car {
// 車種
String CAR_NAME = "トラック";
// 荷台
int carrier;
public void bring() {
System.out.println(CAR_NAME + "が荷物を運びます。");
}
}
// 消防車クラス(サブクラス)
public class FireTruck extends Car {
// 車種
String CAR_NAME = "消防車";
// ホース
int hose;
public void waterDischarge() {
System.out.println(CAR_NAME + "が放水します。");
}
}
上記例では、「トラッククラス」と「消防車クラス」は「車のスーパークラス」を継承している。
継承を使うことで、車の共通的な機能はスーパークラス(親クラス)で管理し、サブクラス(子クラス)では、サブクラス独自の機能を実装するだけとなる。
継承を利用することで、何度も同じソースコードを書かずに済み、読みやすいソースコードを書くことができる。
★ポイント
スーパークラスとサブクラスにis-aの関係があれば継承をつかう。(サブクラス is a スーパクラス)
上記の「車」の例で言うと
車 is a トラック
車 is a 消防車
class Main {
public static void main(String args[]) {
Truck tr = new Truck();
System.out.println(tr.move());
System.out.println(tr.blinker());
System.out.println(tr.bring());
FireTruck ft = new FireTruck();
System.out.println(ft.move());
System.out.println(ft.blinker());
System.out.println(ft.waterDischarge());
}
}
// 出力
車が走ります。
車がウインカーを出します。
トラックが荷物を運びます。
車が走ります。
車がウインカーを出します。
消防車が放水します。
車が走ります。車がウインカーを出します。
と出力されるため、なんの車種なのかがわからない状態です。
トラックが走ります。消防車がウインカーを出します。
と出力したい場合、どうしたらよいでしょうか?
そんな時は「オーバーライド」を使います。
次はオーバーライドの説明です。
オーバーライドとは
・スーパークラスのメソッドをサブクラスのメソッドによって上書きすること。
オーバーライドの使い方
継承で使用した消防車クラスで説明します。
// 消防車クラス(サブクラス)
public class FireTruck extends Car {
// 車種
String CAR_NAME = "消防車";
// ホース
int hose;
public void waterDischarge() {
System.out.println(CAR_NAME + "が放水します。");
}
// オーバーライド
@Override
public void move() {
System.out.println(CAR_NAME + "が走ります。");
}
// オーバーライド
@Override
public void blinker() {
System.out.println(CAR_NAME + "がウインカーを出します。");
}
}
// 出力
消防車が走ります。
消防車がウインカーを出します。
消防車が放水します。
サブクラスでメソッドを再定義するだけです。
ただし、@Overrideのアノテーションをつけましょう。
※必須ではないですが、メソッドがオーバーライドしているということが一目でわかるためつけておくようにしましょう。