今回やること
継承は、既存クラスのフィールドやメソッドを引き継いで、新しいクラスを作る仕組みです。図書館資料の共通部分をLibraryItemへ置き、本だけが持つ著者をBookへ追加します。
前提: Java入門 #20 - throwsと例外の伝播までを終え、クラスとコンストラクタを理解していること。
LibraryItem(親): title、showTitle()
└── Book(子): author、showAuthor()
| 言葉 | 意味 |
|---|---|
| スーパークラス | 継承元の親クラス |
| サブクラス | 継承して作る子クラス |
extends | どのクラスを継承するか指定 |
super(...) | 親クラスのコンストラクタを呼ぶ |
Javaのクラスは最終的にObjectを継承しますが、この回では自分で定義した1段の親子関係だけを扱います。
1. 親クラスを作る
複数の図書館資料で使うタイトルと表示処理をまとめます。
class LibraryItem {
private String title;
LibraryItem(String title) {
this.title = title;
}
void showTitle() {
System.out.println("タイトル: " + title);
}
}
titleはprivateなので、LibraryItemの外から直接変更できません。子クラスは、親から引き継いだshowTitle()を通してタイトルを表示できます。
2. Bookで継承する
class Book extends LibraryItem {
private String author;
Book(String title, String author) {
super(title);
this.author = author;
}
void showAuthor() {
System.out.println("著者: " + author);
}
}
BookはLibraryItemを継承し、著者だけを追加します。super(title)は親のコンストラクタを呼び、親が管理するタイトルを初期化します。
親に引数なしコンストラクタがないため、super(title)を省略するとコンパイルできません。super(...)は子コンストラクタの最初の文に置きます。
完成コードを動かす
InheritanceDemo.javaとして保存します。
class LibraryItem {
private String title;
LibraryItem(String title) {
this.title = title;
}
void showTitle() {
System.out.println("タイトル: " + title);
}
}
class Book extends LibraryItem {
private String author;
Book(String title, String author) {
super(title);
this.author = author;
}
void showAuthor() {
System.out.println("著者: " + author);
}
}
public class InheritanceDemo {
public static void main(String[] args) {
Book book = new Book("Java入門", "Ada");
book.showTitle();
book.showAuthor();
}
}
javac InheritanceDemo.java
java InheritanceDemo
BookにはshowTitle()を書いていませんが、親から引き継いでいるため呼び出せます。showAuthor()はBookだけのメソッドです。
継承を使う判断
継承は「BookはLibraryItemの一種である」のようなis-a関係で使います。コードが似ているだけで親子関係を作ると、親の変更が不要な子にも影響します。
| 質問 | この例 |
|---|---|
| 子は親の一種と言えるか | BookはLibraryItemの一種 |
| 親の機能を子でも使えるか | showTitle()を使える |
| 子固有の情報があるか | authorを追加する |
この回ではメソッドの上書きは行いません。子ごとに同じメソッドの動きを変える方法は、次のポリモーフィズム記事で扱います。
成功確認
タイトル: Java入門
著者: Ada
bookから親のshowTitle()と子のshowAuthor()の両方を呼べれば成功です。
よくあるつまずき
extendsを複数書く
Javaのクラスが直接継承できる親クラスは1つです。複数の役割を表す仕組みはインターフェースで学びます。
親のprivateフィールドを子から直接読む
privateは子クラスからも直接アクセスできません。親が用意したメソッドを使うか、必要な公開方法を設計します。
共通コードだけを理由に継承する
親子として意味が通るか確認します。部品として利用したいだけなら、フィールドに別オブジェクトを持つ構成もあります。
練習
親クラスVehicleにnameとshowName()を用意し、Bicycleが継承してgearCountとshowGearCount()を追加してください。super(name)も使います。
次のステップ
Java入門 #22 - ポリモーフィズムで、子クラスが親のメソッドをオーバーライドする方法を学びます。