前回のまとめ
- 型は大別してプリミティブ型と参照型の2つ。
- プリミティブ型は「箱」のイメージでOK。代入は「値をコピー」
- 参照型は「商品タグ」のイメージ。インスタンスを指し示すのがインスタンス名(変数名)。代入は「商品タグが同じところに繋がる(ポインターのコピー)」
- プリミティブ型と参照型では、代入や比較等で(初学者にとって)直感的でない違いがあるので注意する。この違いはコードを実行して確かめること。
- 文字列や配列は参照型。よく使われるので「特別扱い」されている(使いやすくなっている)。
クラスの継承
本を管理する
(書店を経営しているつもりになって、あるいは自分の蔵書について)本を管理するソフトを作ることを考えよう。まず、本(小説とか)を管理するクラスを作ろう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package d00000.lecture11; public class Book { /** 書籍名 */ public String title; /** 著者 */ public String author; /** 本体価格 */ public int price; /** コンストラクタ */ public Book(String title, String author, int price) { this.title = title; this.author = author; this.price = price; } /** 税込価格を算出 */ public int getTaxIncludedPrice() { return (int) (price * 1.08); } /** 情報をCSV形式(カンマ区切り)で取得 */ public String getInfoAsCsv() { String csv = title + "," + author + "," + getTaxIncludedPrice(); return csv; } } |
このクラスを使った例を次に示す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package d00000.lecture11; public class Main1 { public static void main(String[] args) { Book[] bookList = new Book[4]; bookList[0] = new Book("走れメロス", "太宰治", 2000); bookList[1] = new Book("羅生門", "芥川龍之介", 1000); bookList[2] = new Book("怪人二十面相", "江戸川乱歩", 3000); bookList[3] = new Book("ハリー・ポッター", "J・K・ローリング", 2000); // 価格が最も高い本を探す(ただし同じ価格は考慮しない) Book expensiveBook = bookList[0]; for (int i = 1; i < bookList.length; i++) { if (expensiveBook.price > bookList[i].price) { expensiveBook = bookList[i]; } } System.out.println("最も値段が高い本は" + expensiveBook.title + "で" + expensiveBook.getTaxIncludedPrice() + "円です。"); System.out.println("-- CSV出力 ここから --"); for (int i = 0; i < bookList.length; i++) { System.out.println(bookList[i].getInfoAsCsv()); } System.out.println("-- CSV出力 ここまで --"); } } |
GitHubで見る:
「巻」を管理できるように拡張する
漫画などは「第1巻」、「第2巻」と、同じタイトルでシリーズになっているものが多い。この「巻」の管理はBookクラスではできないので新しくComicクラスを作ることを考えよう。ただし、1から新しく作るのではなく、Bookクラスを元に「巻」に関する情報が扱えるように拡張することを考える。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package d00000.lecture11; public class Comic extends Book { /** 巻数 */ public int volume; /** 全1巻か? */ public boolean inOneVolume; /** コンストラクタ */ public Comic(String title, String author, int price, int volume, boolean inOneVolume) { super(title, author, price); // スーパークラスのコンストラクタを呼ぶ this.volume = volume; this.inOneVolume = inOneVolume; } /** 税込価格を算出(オーバーライド) */ @Override public String getInfoAsCsv() { if (inOneVolume) { // 全1巻の場合は巻数を出力しない(Bookと同じ) return super.getInfoAsCsv(); } else { // 複数巻の場合は巻数を出力する return super.getInfoAsCsv() + "," + volume; } } /** タイトルと巻数 */ public String getTitleWithVolume() { if (inOneVolume) { return title + "(全1巻)"; } else { return title + "(第" + volume + "巻)"; } } } |
ポイント:
- 3行目: 「extends Book」で「Bookクラスを継承する」という意味になる。
- この場合、Bookクラスが「スーパークラス」、Comicクラスが「サブクラス」ととなる。
- Bookクラスにあるメンバー(フィールドとメソッド)が引き継がれる(使える)。
- アクセス修飾子(教科書P.170)によって違いがあるので注意する。
- 4-7行目: Comicクラスだけで使えるフィールド
- 9-14行目: Bookクラスとは違うコンストラクタにしたい(インスタンス化時に追加したフィールドに値をセットしたい)ので定義する
- 11行目: superをメソッドのように使う(括弧をつけて引数を渡す)とスーパークラス(この場合Bookクラス)のコンストラクタが実行される。
- 16-28行目: 巻の情報も出力したいので、getInfoCSVメソッドを上書き(オーバーライド)する。
- 17行目: @Overrideアノテーション(教科書P.180)
- 21,24行目: オーバーライドする前の元のメンバーを使いたい場合は、superに「.」をつけてアクセスする(thisと同じような感じ)。
- 28-35行目: Comicクラスだけで使えるメソッド
このクラスを使った例を次に示す。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package d00000.lecture11; public class Main2 { public static void main(String[] args) { Comic[] comicList = new Comic[5]; comicList[0] = new Comic("ドラえもん", "藤子・F・不二雄", 500, 1, false); comicList[1] = new Comic("ドラえもん", "藤子・F・不二雄", 500, 2, false); comicList[2] = new Comic("永沢君", "さくらももこ", 700, 1, true); comicList[3] = new Comic("クレヨンしんちゃん", "臼井儀人", 800, 1, false); comicList[4] = new Comic("クレヨンしんちゃん", "臼井儀人", 800, 2, false); // タイトル一覧 System.out.println("タイトル一覧"); for (Comic comic : comicList) { System.out.println(comic.getTitleWithVolume()); } System.out.println("-- CSV出力 ここから --"); for (Comic comic : comicList) { System.out.println(comic.getInfoAsCsv()); } System.out.println("-- CSV出力 ここまで --"); } } |
GitHubで見る: