この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
更新日時:2026-05-13 09:20:42
タイトル: 継承
本稿は Java の継承に関する記事です。継承とは、既存のクラス (親クラス・スーパークラス) が持つフィールド・メソッドを、新しいクラス (子クラス・サブクラス) でそのまま引き継いで利用する仕組みです。共通ロジックを 1 箇所にまとめ、差分だけ子クラスに書く設計を可能にします。
継承の構文
|
class 子クラス名 extends 親クラス名 {
// 子クラス固有の処理 / オーバーライド
}
|
継承の具体例
|
// 親クラス
public class Animal {
protected final String name;
public Animal(String name) {
this.name = name;
}
public String greet() {
return name + ": hello";
}
}
// 子クラス
public class Dog extends Animal {
public Dog(String name) {
super(name); // 親のコンストラクタ呼び出し
}
@Override
public String greet() {
return super.greet() + ", woof!";
}
}
Animal a = new Dog("Pochi");
System.out.println(a.greet()); // Pochi: hello, woof!
|
継承で出来ること
| 仕組み | 概要 |
| フィールド・メソッドの継承 | 親クラスの protected / public なメンバを子側でそのまま使える |
| メソッドのオーバーライド | 同じシグネチャで挙動を上書きする (@Override を付ける) |
| 多態性 (ポリモーフィズム) | 親クラスの型変数で子インスタンスを扱える |
| 抽象クラス・抽象メソッド | 共通ロジック + 必須実装を子へ強制 |
| final で禁止 | クラスやメソッドの継承・オーバーライドを禁止 |
Java の継承ルール
- クラスの多重継承は不可 (extends は 1 つだけ)。複数の振る舞いを取り込みたい場合はインタフェースを
implements する
- すべてのクラスは暗黙的に
java.lang.Object を継承
- コンストラクタは継承されない。子側で自分のコンストラクタを定義する
- 子のコンストラクタ先頭で親のコンストラクタが必ず呼ばれる (明示しなければ
super())
private メンバは継承されるが、子からは直接アクセスできない
static メンバも継承されるが、本質的にはクラス共有なのでオーバーライドの代わりに「隠蔽 (hiding)」になる
- インタフェースは多重実装可。Java 8 以降は
default メソッドで実装も持てる
アクセス修飾子と継承可視性
| 修飾子 | 同一クラス | 同一パッケージ | 子クラス | 他 |
public | ○ | ○ | ○ | ○ |
protected | ○ | ○ | ○ | × |
| (無指定 / package-private) | ○ | ○ | × | × |
private | ○ | × | × | × |
オーバーライドのルール
- シグネチャ (メソッド名・引数の型と数) が親と一致すること
- 戻り値は親と同じか、共変な (より狭い) 型でも可
- アクセス修飾子は親と同等以上の公開度 (狭めるのは不可)
- チェック例外は親が宣言しているもの以下に限る
@Override アノテーションをつけてコンパイラチェックを利用
継承と合成 (Composition) の使い分け
| 判断軸 | 継承 | 合成 (フィールドとして保持) |
| 関係性 | 「〜は〜である (is-a)」 | 「〜は〜を持つ (has-a)」 |
| 結合度 | 強い | 弱い |
| 差分実装の柔軟性 | 制限される | 柔軟 |
| テスト容易性 | 親に依存して難しくなりがち | モック差し替えしやすい |
近年は「Composition over Inheritance」(継承より合成) の方針が主流です。継承は本当に is-a 関係がある場合のみ使い、ふるまいの差し替えはインタフェース+実装注入を活用します。
注意点
- final クラス / final メソッドは継承・オーバーライド禁止 (
String は final クラス)
- 深い継承階層は理解しづらく壊れやすい。2〜3 階層に留めるのが目安
- サブクラスから親のprotected フィールドを書き換える設計は脆い。getter / setter 経由が安全
- equals / hashCode の継承はサブクラスで再定義が必要なケースが多い
- 差分プログラミング (Diff Programming) の手段としての継承の濫用は強い密結合を生み、変更コストを上げる
関連