手を動かして学ぶ Java入門 (クラス継承の超基本)
環境構築不要! ブラウザから直接コードを実行できます。
本記事では、クラスの継承について基本の基本を学びます。
15分くらいで、さくっと終わる記事をめざしています。
シリーズ一覧
- シリーズ
- 手を動かして学ぶ Java入門 (Hello world 編)
- 手を動かして学ぶ Java入門 (数値と演算)
- 手を動かして学ぶ Java入門 (数値と変数)
- 手を動かして学ぶ Java入門 (コメントの書き方)
- 手を動かして学ぶ Java入門 (文と式の違い)
- 手を動かして学ぶ Java入門 (if文)
- 手を動かして学ぶ Java入門 (if-else文、if-elseif文)
- 手を動かして学ぶ Java入門 (文字列の連結)
- 手を動かして学ぶ Java入門 (while文)
- 手を動かして学ぶ Java入門 (break文)
- 手を動かして学ぶ Java入門 (continue文)
- 手を動かして学ぶ Java入門 (for文)
- 手を動かして学ぶ Java入門 (クラスの超基本)
- 手を動かして学ぶ Java入門 (クラス・メソッド)
- 手を動かして学ぶ Java入門 (クラス・フィールド)
- 手を動かして学ぶ Java入門 (クラス・コンストラクタ)
- 手を動かして学ぶ Java入門 (文字列クラス)
- 手を動かして学ぶ Java入門 (静的メソッド)
- 手を動かして学ぶ Java入門 (静的フィールド)
- 手を動かして学ぶ Java入門 (定数の定義)
- 手を動かして学ぶ Java入門 (クラス継承の超基本)
- 手を動かして学ぶ Java入門 (メソッドのオーバーライド)
- 手を動かして学ぶ Java入門 (メソッドのオーバーロード)
続きは近日公開予定!
はじめに
この記事は paiza.IO の「Online Java compiler」を利用しています。
2024/12/17 現在、上記環境の Java バージョンは 18 です。(paiza.IO利用ガイド)
実行したコードは paiza.IO で保存および公開されることがあります。
そのため、個人情報などの機密性の高い情報は、コードとして入力しないようにご注意ください。
詳細は paiza.IO の利用規約およびプライバシーポリシーをご確認ください。
クラスのおさらい
クラスとは、具体的に いうと…
- フィールド (変数)
- メソッド (関数)
この2つが集まったものです。
フィールド(変数) は、数値などを保存しておく箱のようなものです。
メソッド(関数) は、プログラムの実際の処理を書きます。
足し算や引き算などの計算をしたり、その結果を画面に出力したり、などなどです。
例えば、次の Sample クラスでは、
- value フィールド
- print メソッド
を宣言しています。
public class Sample {
private int value = 123;
public void print() {
System.out.println("value = " + value);
}
}
クラスの継承
クラスの継承とは、簡単にいうと…
- ベースとなるクラスの フィールド と メソッド
- それを 引き継いだ 新しいクラスを作る (宣言する)
ことです。
ベースとなるクラスのことは、
- 基底クラス
- 親クラス
- スーパークラス
- ベースクラス
などと呼ばれます。
この記事では、スーパークラス で表記を統一します。
継承して作った新しいクラスのことは、
- 派生クラス
- 子クラス
- 拡張クラス
- サブクラス
などと呼ばれます。
この記事では、サブクラス で表記を統一します。
イメージとしては、サブクラスの中にスーパークラスを取り込んでいる感じですかね。
目的
継承の主な目的は次の2つです。
- 共通するクラス構成 (フィールドとメソッド) を再利用
- ポリモーフィズム (多態性) の実現
1つめは比較的イメージしやすいかと思います。
クラスをいくつか作っていたら、似たような構成(フィールドやメソッド) になったので、共通部分を1か所にまとめたい…
そんなときは、スーパークラスに共通部分をまとめて使います。
2つめの ポリモーフィズム は、プログラミングにおいてとても大事な概念です。
個人的には、1つめの目的よりこちらのほうが重要だと考えています。
ただ、まだ少し難しい概念だと思いますので、今回の記事では割愛します。
気になるかたは「ポリモーフィズム - Wikipedia」などをご参照ください。
補足
- クラスの継承は、むやみに使いすぎると「クラス構成が複雑になる」「クラス間の依存度が強くなる」といったデメリットもあります。
- このあたりの話 (依存度など) も入門としては少し難しいので割愛します…
コード例
具体的なコード例でクラスの継承を見てみましょう。
まずは Counter クラスです。
このクラスは、フィールドとして count を持ちます。
そして、increment メソッドで count を +1 して、print メソッドでその内容を出力します。
public class Counter {
private int count;
public void increment() {
count++;
}
public void print() {
System.out.println("count = " + count);
}
}
それでは、この Counter クラスを実際に使ってみましょう。
結果がどうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは2ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか? 「出力」のところに
count = 1
count = 2
と表示されたら成功です。
ここまでは、前回までに学習した内容ですね。
さて、次はいよいよクラスの 継承 です。
先ほどの Counter クラスを継承した SubCounter クラスを宣言してみましょう。
継承するには、extends キーワードを使います。
"extend" は直訳すると「拡張する」という意味ですね。
そこに三単現の s をつけて extends となります。
public class SubCounter extends Counter {
}
SubCounter クラスの中身は空ですが、これでも Counter クラスを継承できています。
Counter が スーパークラス、SubCounter が サブクラス です。
それでは、この SubCounter クラスを使ってみましょう。
SubCounter クラスは、Counter クラスのメソッドを 引き継いで います。
結果がどうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか? 「出力」のところに
count = 1
count = 2
と表示されたら成功です。
結果は同じですね。
SubCounter クラスの中身は空です。
しかし、ちゃんと Counter クラスのフィールドとメソッドを引き継いでいるのが確認できました。
宣言
サブクラスの宣言の基本は
- 通常のクラス宣言 + extends + スーパークラス名
となります。
先ほどの Counter クラスと SubCounter クラスを例に見てみましょう。
Counter クラスがスーパークラス、SubCounter クラスがサブクラスです。
public class SubCounter extends Counter {
^^^^^^^^^^^^^^^^^^^^^^^ <--- 通常のクラス宣言
}
public class SubCounter extends Counter {
^^^^^^^ <--- 継承のためのキーワード
}
public class SubCounter extends Counter {
^^^^^^^^^^ <--- スーパークラス名
}
アクセス修飾子
フィールドとメソッドのアクセス修飾子は、これまでの記事で次のように学びました。
- public : クラスの外からアクセスできる
- private : クラスの外からアクセスできない
表にすると次のようになります。
アクセス修飾子 | クラスの外からのアクセス | クラス内部からのアクセス |
---|---|---|
public | 〇 | 〇 |
private | × | 〇 |
それでは、サブクラスからスーパークラスへのアクセスはどうなるのでしょうか?
正解は、クラスの外からのアクセスと同じになります。
アクセス修飾子 | サブクラスからスーパークラスへアクセス |
---|---|
public | 〇 |
private | × |
Counter クラスを例に見てみましょう。
先ほどまでとは違い print メソッドはありません。
ポイントは、count フィールドのアクセス修飾子は private であるということです。
public class Counter {
private int count;
public void increment() {
count++;
}
}
次はサブクラスです。
print メソッドはこちらに宣言しました。
public class SubCounter extends Counter {
public void print() {
System.out.println("サブクラスからアクセス : count = " + count);
}
}
さて、SubCounter クラスから、Counter (スーパークラス) の count フィールドにアクセスしようとしています。
どうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか?
SubCounter.java:3: error: count has private access in Counter
System.out.println("サブクラスからアクセス : count = " + count);
^
1 error
とエラーになれば成功です。
"count has private access in Counter" とは、意訳すると
- count フィールドは Counter クラスの private なフィールドです。(よって外からはアクセスできません)
という感じです。
このように、スーパークラスの private なフィールド(とメソッド) は、サブクラスからはアクセスできません。
応用問題
【問題】
まずは、下記のプログラムをそのまま「実行(Ctrl-Enter)」してみましょう。
結果はコンパイルエラーになったはずです。
Main.java:7: error: cannot find symbol
counter.print();
^
... 省略 ...
これは、SubCounter クラスに print メソッドが宣言されていないからです。
そこで問題です。
SubCounter クラスに対して、次の2つの修正をいれてください。
- Counter クラスを継承させる
- incrementDouble メソッドに、カウンタを +2 させる処理を追加
その結果として、プログラムを実行すると、
count = 2
count = 4
と「出力」に表示されるはずです。
それでは、SubCounter クラスを修正してから「実行(Ctrl-Enter)」してみましょう。
(修正するのは SubCounter クラスだけです)
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
無事に、
count = 2
count = 4
と出力されましたでしょうか?
もし解けなかった場合は、下記の回答例をご参照ください。
回答例
【コード】
// Counter クラスを継承してください。
public class SubCounter extends Counter {
public void incrementDouble() {
// 必要な処理を追加してください。
increment();
increment();
}
}
※ Main.java, Counter.java は書き換えません。
【出力】
count = 2
count = 4
まとめ
クラスの継承とは、ベースとなるクラスの
- フィールド
- メソッド
を引き継いだクラスを作ることをいいます。
ぜひ有効に活用していきたいですね。
次回は「手を動かして学ぶ Java入門 (メソッドのオーバーライド)」になります。
関連記事
- シリーズ
- 手を動かして学ぶ Java入門 (Hello world 編)
- 手を動かして学ぶ Java入門 (数値と演算)
- 手を動かして学ぶ Java入門 (数値と変数)
- 手を動かして学ぶ Java入門 (コメントの書き方)
- 手を動かして学ぶ Java入門 (文と式の違い)
- 手を動かして学ぶ Java入門 (if文)
- 手を動かして学ぶ Java入門 (if-else文、if-elseif文)
- 手を動かして学ぶ Java入門 (文字列の連結)
- 手を動かして学ぶ Java入門 (while文)
- 手を動かして学ぶ Java入門 (break文)
- 手を動かして学ぶ Java入門 (continue文)
- 手を動かして学ぶ Java入門 (for文)
- 手を動かして学ぶ Java入門 (クラスの超基本)
- 手を動かして学ぶ Java入門 (クラス・メソッド)
- 手を動かして学ぶ Java入門 (クラス・フィールド)
- 手を動かして学ぶ Java入門 (クラス・コンストラクタ)
- 手を動かして学ぶ Java入門 (文字列クラス)
- 手を動かして学ぶ Java入門 (静的メソッド)
- 手を動かして学ぶ Java入門 (静的フィールド)
- 手を動かして学ぶ Java入門 (定数の定義)
- 手を動かして学ぶ Java入門 (クラス継承の超基本)
- 手を動かして学ぶ Java入門 (メソッドのオーバーライド)
- 手を動かして学ぶ Java入門 (メソッドのオーバーロード)