書籍を表すBookクラスを継承して、漫画本(巻という概念がある)を表すクラスを作ろう。
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package lesson11.d00000; 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 String getInfo() { String info = title + ", " + author +", " + price + "円"; return info; } } |
1 2 3 4 5 6 7 8 9 10 |
package lesson11.d00000; public class Comic extends Book { public int volume; public Comic(String title, String author, int price, int volume) { super(title, author, price); this.volume = volume; } } |
mainメソッドで、それぞれ使ってみよう。
1 2 3 4 |
Book book1 = new Book("Javaの絵本", "アンク", 1580); System.out.println(book1.getInfo()); Comic comic1 = new Comic("ドラえもん", "藤子不二雄", 500, 1); System.out.println(comic1.getInfo()); |
実行結果:
Javaの絵本, アンク, 1580円
ドラえもん, 藤子不二雄, 500円
Comicのコンストラクタ
- 継承したクラス(サブクラス)のコンストラクタでは、スーパークラスのコンストラクタを最初に呼ばなければならない。
- スーパークラスのコンストラクタはsuper(引数)で呼ぶことができる。
- スーパークラスに引数なしのコンストラクタ(デフォルトコンストラクタを含む)がある場合、「super();」という記述を省略することができる(つまり書かなくても呼ばれる)。
オーバーライド
- スーパークラスと同じメソッドを定義するとそのメソッドを上書きすることができる。
- スーパークラスのメソッドは super.メソッド名(引数)で呼び出すことができる。
- @Overrideはなくてもいいが、つけておくとオーバーライドできているかチェックしてくれる(アノテーション)。
1 2 3 4 5 |
@Override public String getInfo() { String info = super.getInfo() + ", " + volume + "巻"; return info; } |
実行結果:
Javaの絵本, アンク, 1580円
ドラえもん, 藤子不二雄, 500円, 1巻
合計金額を計算する(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
ArrayList<Book> bookList = new ArrayList<Book>(); bookList.add(new Book("Java逆引きレシピ", "竹添他", 2800)); bookList.add(new Book("Kotlinスタートブック", "長澤", 3500)); ArrayList<Comic> comicList = new ArrayList<Comic>(); comicList.add(new Comic("ドラゴンボール", "鳥山", 500, 1)); comicList.add(new Comic("ドラゴンボール", "鳥山", 500, 2)); int totalPrice1 = 0; for (int i=0; i<bookList.size(); i++) { Book b = bookList.get(i); totalPrice1 += b.price; } for (Comic c : comicList) { // 拡張for文[教科書P.170] totalPrice1 += c.price; } System.out.println("合計金額は" + totalPrice1 + "円です。"); |
代入記号の意味
プリミティブ型(基本型)は「箱」のイメージ。代入によって、値がコピーされて箱に格納される。
クラス型(参照型)は「タグ」のイメージ。
代入によって、同じインスタンスに結びつく。
もっと色々知りたい人のために:
- タグが1つも付いていないインスタンスはどうなるのか?→GC(ガベージコレクション、ゴミ集め)によってメモリから消えて無くなる。[教科書P.82]
- Null Pointer(ヌルポ)とは、タグの先にインスタンスがない状態のこと。
- クラス型のインスタンスをコピーするのはどうするのか?→自分で実装する。大抵はcloneメソッドをオーバーライドする。
- インスタンスをコピーするコードを書いたけど、思った通りにコピーされてない。→シャローコピー(shallow copy)とディープコピー(deep copy)について調べよう。
サブクラスのインスタンスをスーパークラスのインスタンスとして扱う
Comicクラスのインスタンスは、Bookクラスのインスタンスとして扱うことができる。なぜならComicクラスはBookクラスを受け継いでいるから(継承しているから)。
多態性[教科書P.108]
1 2 3 |
Comic comic2 = new Comic("ワンピース", "尾田", 500, 1); Book book2 = (Book)comic2; System.out.println(book2.getInfo()); |
- comic2で呼び出すときは、Comicとして扱うので、volumeフィールドにアクセスできる。
- book2で呼び出すときは、Bookとして扱うので、volumeフィールドにアクセスできない。
- book2.getInfo()は上書きした方(ComicのgetInfo)が呼び出される(Bookとして扱う場合であっても、実体はComicクラスのインスタンスだから)。
合計金額を計算する(2)
1 2 3 4 5 6 7 8 9 10 |
ArrayList<Book> bookAndComicList = new ArrayList<>(); bookAndComicList.add(new Book("Java逆引きレシピ", "竹添他", 2800)); bookAndComicList.add(new Book("Kotlinスタートブック", "長澤", 3500)); bookAndComicList.add(new Comic("ドラゴンボール", "鳥山", 500, 1)); bookAndComicList.add(new Comic("ドラゴンボール", "鳥山", 500, 2)); int totalPrice2 = 0; for (Book b : bookAndComicList) { totalPrice2 += b.price; } System.out.println("合計金額は" + totalPrice2 + "円です。"); |