
Java道|Javaの継承の基本と使い方
親の力を受け継ぎ、子クラスで自分だけの技を加える。
Javaの継承は、共通部分をまとめて、クラスを強く育てるための仕組みです。
Javaのオブジェクト指向では、すでに作ったクラスを土台にして、新しいクラスを作ることができます。
この仕組みを 継承 といいます。
継承を使うと、似たような性質を持つクラスを毎回最初から作らなくてよくなります。
共通している情報や処理は親クラスにまとめておき、子クラスでは必要な特徴だけを追加できます。
鬼滅の刃風にたとえると、まず鬼殺隊士という共通の土台があります。
鬼殺隊士であれば、名前を持ち、階級を持ち、任務に出ることができます。
そこから、柱のような特別な隊士を作る場合、鬼殺隊士としての基本はそのまま受け継ぎます。
そのうえで、担当区域や指揮能力のような追加要素を持たせるイメージです。
つまり継承は、
| 考え方 | 内容 |
|---|---|
| 共通部分 | 親クラスにまとめる |
| 個別の特徴 | 子クラスに追加する |
| 目的 | コードの重複を減らし、拡張しやすくする |
という考え方です。今回の記事では、継承、スーパークラス、サブクラス、extends、クラスの拡張について、鬼滅の刃風の世界観に置きかえて解説します。
継承とは何か
継承とは、すでにあるクラスのフィールドやメソッドを受け継いで、新しいクラスを作る仕組みです。
鬼滅の刃風にたとえると、まず DemonSlayer という鬼殺隊士の共通クラスがあるとします。
このクラスには、鬼殺隊士なら多くの人が持っている基本情報をまとめます。
たとえば、次のようなものです。
| 項目 | 内容 |
|---|---|
| 名前 | 隊士の名前 |
| 階級 | 隊士としての階級 |
| 行動 | 状態を表示する、任務に出る |
この共通の土台をもとにして、さらに特別な隊士を表すクラスを作れます。
たとえば、柱のような特別な役割を持つ隊士を表すなら、次のように考えられます。
| クラス名 | 役割 |
|---|---|
| DemonSlayer | 鬼殺隊士の共通の土台 |
| PillarSlayer | 鬼殺隊士を受け継いだ特別な隊士 |
このとき、PillarSlayer は DemonSlayer の機能を受け継ぎます。
さらに、PillarSlayer だけが持つ情報や機能を追加できます。
つまり継承とは、
親クラスの基本能力を受け継ぎながら、子クラスで新しい特徴を加える仕組み
です。
↓クリックすると拡大表示されます。

クラスを拡張するとはどういうことか
クラスを拡張するとは、もともとあるクラスを土台にして、新しいフィールドやメソッドを追加したクラスを作ることです。
鬼滅の刃風にたとえると、普通の鬼殺隊士を土台にして、柱としての役割を追加するイメージです。
たとえば、鬼殺隊士には次のような共通情報があります。
| 共通情報 | 内容 |
|---|---|
| name | 名前 |
| rank | 階級 |
| setSlayer() | 名前と階級を設定する |
| show() | 状態を表示する |
ここから、柱クラスには次のような追加情報を持たせます。
| 追加情報 | 内容 |
|---|---|
| area | 担当区域 |
| setArea() | 担当区域を設定する |
このとき大切なのは、親クラスにある name、rank、setSlayer()、show() を子クラスにもう一度書かなくてもよいことです。
子クラスは親クラスを受け継いでいるため、親クラスの機能を使えます。
これがクラスを拡張する大きなメリットです。
図:親クラスから子クラスへ受け継ぐイメージ
↓クリックすると拡大表示されます。

この図が示していること
この図では、上にある DemonSlayer クラスが親クラスです。
そこから下の PillarSlayer クラスへ矢印が伸びています。
この矢印は、DemonSlayer のメンバが PillarSlayer に受け継がれていることを表します。
PillarSlayer の中には、親から受け継いだ name、rank、setSlayer()、show() があります。
さらに、PillarSlayer 独自の area、setArea() も追加されています。
つまり、サブクラスは、
| 受け継ぐもの | 追加するもの |
|---|---|
| 親クラスの共通機能 | 子クラス独自の特徴 |
を両方持てるということです。
スーパークラスとサブクラス
継承では、親と子の関係を表すために、次の用語を使います。
| 用語 | 意味 | 鬼滅の刃風にたとえると |
|---|---|---|
| スーパークラス | 継承元になる親クラス | 鬼殺隊士という共通の土台 |
| サブクラス | 親を受け継いで作る子クラス | 柱のように特別な役割を持つ隊士 |
今回の例では、次の関係になります。
| クラス名 | 役割 |
|---|---|
| DemonSlayer | スーパークラス |
| PillarSlayer | サブクラス |
ここで大切なのは、サブクラスはスーパークラスとまったく別の存在ではないという点です。
PillarSlayer は、PillarSlayer としての独自要素を持ちながら、DemonSlayer としての性質も持っています。
鬼滅の刃風にたとえると、
柱は特別な隊士だが、まず鬼殺隊士でもある
という関係です。
このように、子クラスは親クラスの一種として考えると、継承の関係が理解しやすくなります。
extends の意味
Javaでクラスを継承するときは、extends を使います。
書き方は次の形です。
class サブクラス名 extends スーパークラス名
{
サブクラスに追加するメンバ
}たとえば、PillarSlayer が DemonSlayer を継承する場合は、次のように書きます。
class PillarSlayer extends DemonSlayer
{
// 柱だけの追加要素
}この extends は、
このクラスは指定した親クラスを受け継いで作ります
という意味です。
とても短い記述ですが、意味は大きいです。
この1行によって、PillarSlayer は DemonSlayer にあるメソッドを使えるようになります。
クラスの継承を確認する
ファイル名:Sample1.java
class DemonSlayer
{
private String name;
private String rank;
public DemonSlayer()
{
name = "隊士未登録";
rank = "階級未設定";
System.out.println("鬼殺隊士クラスの隊士を作成しました。");
}
public void setSlayer(String n, String r)
{
name = n;
rank = r;
System.out.println("名前を" + name + "に、階級を" + rank + "にしました。");
}
public void show()
{
System.out.println("隊士の名前は" + name + "です。");
System.out.println("階級は" + rank + "です。");
}
}
class PillarSlayer extends DemonSlayer
{
private int area;
public PillarSlayer()
{
area = 0;
System.out.println("柱クラスの隊士を作成しました。");
}
public void setArea(int a)
{
area = a;
System.out.println("担当区域を" + area + "にしました。");
}
}
class Sample1
{
public static void main(String[] args)
{
PillarSlayer slayer1 = new PillarSlayer();
slayer1.setSlayer("水月", "水柱");
slayer1.setArea(7);
slayer1.show();
}
}このプログラムの全体像
このプログラムでは、DemonSlayer がスーパークラス、PillarSlayer がサブクラスです。
それぞれの役割を整理すると、次のようになります。
| クラス | 持っているもの |
|---|---|
| DemonSlayer | 名前、階級、名前と階級を設定する機能、状態表示機能 |
| PillarSlayer | 担当区域、担当区域を設定する機能 |
ここで注目したいのは、PillarSlayer クラスの中に name、rank、setSlayer()、show() を書いていないことです。
それでも、main メソッドでは次のように使えています。
slayer1.setSlayer("水月", "水柱");
slayer1.show();これは、PillarSlayer が DemonSlayer を継承しているからです。
つまり、PillarSlayer のオブジェクトは、自分自身が持つ setArea() だけでなく、親クラスから受け継いだ setSlayer() や show() も使えます。
スーパークラス DemonSlayer の役割
まず、親クラスである DemonSlayer を見てみましょう。
class DemonSlayer
{
private String name;
private String rank;ここでは、鬼殺隊士に共通する情報として name と rank を持たせています。
鬼滅の刃風にたとえると、どの隊士にも名前と階級があります。
これは柱だけでなく、一般隊士にも共通する情報です。
だから、DemonSlayer にまとめるのが自然です。
DemonSlayer には、次のメソッドもあります。
| メソッド | 役割 |
|---|---|
| DemonSlayer() | 隊士を初期状態で作る |
| setSlayer(String n, String r) | 名前と階級を設定する |
| show() | 隊士の状態を表示する |
これらは、特別な隊士だけの機能ではありません。
鬼殺隊士として共通して使えそうな機能です。
継承を使うときは、まずこのように考えます。
| 見るポイント | 考え方 |
|---|---|
| 全員に共通するか | 共通するなら親クラスへ |
| 特定の種類だけが持つか | 特定のものなら子クラスへ |
DemonSlayer は、鬼殺隊士全体の共通部分をまとめる役割を持っています。
サブクラス PillarSlayer の役割
次に、子クラスである PillarSlayer を見てみましょう。
class PillarSlayer extends DemonSlayer
{
private int area;ここでは、extends DemonSlayer と書いています。
これにより、PillarSlayer は DemonSlayer を継承します。
PillarSlayer では、親クラスから受け継いだ機能に加えて、area を追加しています。
この area は、柱が担当する区域のようなものです。
鬼滅の刃風にたとえると、柱はただの隊士ではなく、特定の地域や任務を任される立場です。
そのため、担当区域という追加情報を持たせています。
さらに、setArea() で担当区域を設定します。
public void setArea(int a)
{
area = a;
System.out.println("担当区域を" + area + "にしました。");
}この setArea() は PillarSlayer 独自のメソッドです。
DemonSlayer にはありません。
つまり PillarSlayer は、
| 受け継いだ機能 | 独自に追加した機能 |
|---|---|
| setSlayer() | setArea() |
| show() | area の管理 |
| name と rank の管理 |
という形で、親の機能と子の機能を組み合わせています。
サブクラスのコンストラクタ
PillarSlayer のコンストラクタは次の部分です。
public PillarSlayer()
{
area = 0;
System.out.println("柱クラスの隊士を作成しました。");
}ここでは、PillarSlayer 独自のフィールドである area を初期化しています。
鬼滅の刃風にたとえると、柱として隊士を登録したときに、担当区域をいったん 0 にしておくようなイメージです。
ここで見ておきたいのは、サブクラスのコンストラクタでは、子クラスで追加した要素を中心に初期化していることです。
親クラスにある name や rank は DemonSlayer 側で管理しています。
子クラスである PillarSlayer は、自分に追加された area を管理します。
このように、親と子で役割を分けると、コードの見通しがよくなります。
main メソッドの流れ
main メソッドでは、次の流れで処理が進みます。
PillarSlayer slayer1 = new PillarSlayer();ここでは、PillarSlayer 型のオブジェクトを作っています。
slayer1 は、柱クラスの隊士として生成されます。
次に、名前と階級を設定しています。
slayer1.setSlayer("水月", "水柱");この setSlayer() は PillarSlayer には書かれていません。
しかし、親クラス DemonSlayer にあるため、PillarSlayer のオブジェクトから呼び出せます。
次に、担当区域を設定しています。
slayer1.setArea(7);この setArea() は PillarSlayer に追加された独自メソッドです。
最後に、状態を表示しています。
slayer1.show();show() も DemonSlayer から受け継いだメソッドです。
処理の流れを表にすると、次のようになります。
| 呼び出し | 定義されている場所 | 意味 |
|---|---|---|
| new PillarSlayer() | PillarSlayer | 柱クラスの隊士を作る |
| setSlayer("水月", "水柱") | DemonSlayer | 名前と階級を設定する |
| setArea(7) | PillarSlayer | 担当区域を設定する |
| show() | DemonSlayer | 隊士の状態を表示する |
この表を見ると、1つのオブジェクトが親クラスと子クラスの両方の機能を使っていることが分かります。
これが継承の大きな特徴です。
実行結果の例
鬼殺隊士クラスの隊士を作成しました。
柱クラスの隊士を作成しました。
名前を水月に、階級を水柱にしました。
担当区域を7にしました。
隊士の名前は水月です。
階級は水柱です。実行結果では、まず鬼殺隊士クラスのメッセージが表示され、そのあと柱クラスのメッセージが表示されます。
これは、PillarSlayer のオブジェクトを作るとき、親クラスである DemonSlayer の部分も関係しているためです。
そのあと、名前と階級を設定し、担当区域を設定しています。
最後に show() によって、隊士の名前と階級が表示されます。
継承を使うと何が便利なのか
継承の大きな利点は、共通部分を何度も書かなくてよいことです。
たとえば、PillarSlayer クラスを作るときに、名前や階級、状態表示の処理をもう一度全部書くと、コードが重複してしまいます。
しかし、DemonSlayer に共通部分をまとめておけば、PillarSlayer では追加したいものだけを書けばよくなります。
継承のメリットを整理すると、次のようになります。
| 利点 | 内容 |
|---|---|
| 重複が減る | 同じフィールドやメソッドを何度も書かなくてよい |
| 見通しがよくなる | 共通部分と追加部分を分けて考えられる |
| 修正しやすい | 共通処理を親クラス側でまとめて変更できる |
| 拡張しやすい | 新しいサブクラスを追加しやすい |
鬼滅の刃風にたとえると、鬼殺隊士としての基本情報を毎回書き直す必要はありません。
鬼殺隊士の共通台帳を作っておき、柱なら柱用の追加情報だけを書き足すような感覚です。
図:オブジェクトが親と子の機能を使うイメージ
↓クリックすると拡大表示されます。

この図が示していること
この図では、slayer1 という PillarSlayer オブジェクトの中に、親から受け継いだ機能と、自分で追加した機能が一緒に存在している様子を表しています。
親クラス DemonSlayer からは、setSlayer() や show() を受け継いでいます。
子クラス PillarSlayer では、setArea() や area を追加しています。
つまり、サブクラスのオブジェクトは、
| 種類 | 使えるもの |
|---|---|
| 親から受け継いだもの | setSlayer()、show() など |
| 子で追加したもの | setArea()、area など |
を両方使えるということです。
継承を鬼滅の刃風に感覚で理解する
鬼殺隊士という共通の型があるとします。
その型には、次のような基本があります。
| 共通の基本 | 内容 |
|---|---|
| 名前 | 誰なのか |
| 階級 | どの立場なのか |
| 状態表示 | 自分の情報を示す |
そこから、柱という特別な型を作るとします。
柱は、鬼殺隊士としての基本を持ちながら、さらに担当区域のような情報を持ちます。
つまり、
鬼殺隊士としての共通部分を受け継ぎ、柱としての特徴を追加する
ということです。
これが継承の感覚です。
Javaのコードでは、この関係を extends で表します。
class PillarSlayer extends DemonSlayerこの1行によって、PillarSlayer は DemonSlayer の性質を受け継いだクラスになります。
継承で大切な親子関係の考え方
継承は便利ですが、何でもかんでも使えばよいわけではありません。
大切なのは、親子関係が自然かどうかです。
継承を使うときは、次のように考えると分かりやすいです。
| 判断ポイント | 例 |
|---|---|
| 子クラスは親クラスの一種と言えるか | PillarSlayer は DemonSlayer の一種 |
| 共通部分を親にまとめられるか | 名前、階級、状態表示 |
| 子クラスだけの追加要素があるか | 担当区域、担当区域設定 |
今回の例では、PillarSlayer は DemonSlayer の一種です。
そのため、継承として自然です。
鬼滅の刃風にたとえると、
| 関係 | 継承として自然か |
|---|---|
| 柱は鬼殺隊士の一種 | 自然 |
| 鬼殺隊士は刀の一種 | 不自然 |
| 水柱は柱の一種 | 自然 |
このように、子クラスは親クラスの一種である、という関係で考えると、継承を使うべき場面が見えてきます。
private のフィールドはどう考えるか
Sample1.java では、DemonSlayer の name と rank に private を付けています。
private String name;
private String rank;private が付いているフィールドは、そのクラスの外から直接触れません。
つまり、PillarSlayer は DemonSlayer を継承していますが、name や rank を直接操作するのではなく、setSlayer() や show() を通して扱います。
これは、鬼滅の刃風にたとえると、隊士名簿の重要情報を勝手に書き換えられないようにしているイメージです。
| 書き方 | 意味 |
|---|---|
| private String name | 名前を外部から直接変更させない |
| setSlayer() | 決められた方法で名前と階級を設定する |
| show() | 決められた方法で状態を表示する |
継承しているからといって、親クラスの private フィールドを子クラスが自由に直接触れるわけではありません。
この点は、継承を学ぶときに大切です。
親クラスと子クラスの役割分担
継承では、親クラスと子クラスの役割分担を意識すると理解しやすくなります。
今回の例では、次のように分かれています。
| 担当 | 内容 |
|---|---|
| DemonSlayer | 鬼殺隊士としての共通情報を持つ |
| PillarSlayer | 柱としての追加情報を持つ |
| main メソッド | オブジェクトを作って、親と子の機能を使う |
親クラスには、共通して使うものを置きます。
子クラスには、その子クラスだけが必要とするものを置きます。
この切り分けができると、クラス設計がかなり分かりやすくなります。
継承は設計の再利用である
継承をひとことで表すなら、設計の再利用です。
一度作った親クラスを活かしながら、新しいクラスを作れます。
これにより、共通部分を繰り返し書かずに済みます。
鬼滅の刃風にたとえると、鬼殺隊士としての共通ルールを最初に作っておきます。
そのうえで、水柱、炎柱、音柱のように、必要な特徴を追加していくイメージです。
Javaで継承を学ぶときは、文法だけを見るのではなく、次の視点を持つと理解しやすくなります。
| 視点 | 考えること |
|---|---|
| 共通部分 | どのクラスにも必要なものは何か |
| 追加部分 | 子クラスだけに必要なものは何か |
| 親子関係 | 子クラスは親クラスの一種と言えるか |
| 再利用 | 親クラスの機能を使い回せるか |
継承は、クラスを強くするための仕組みです。
親クラスに共通の力をまとめ、子クラスで個性を加えることで、コードは読みやすく、拡張しやすくなります。
