【Java学習|豆知識】Javaの継承をマスターしよう:extendsが導く拡張性と設計の美学

導入

Javaにおける「継承」は、オブジェクト指向プログラミングの根幹を成す機能です。extendsキーワードを使うことで、既存のクラスやインターフェースの機能を再利用し、新たな機能を追加できます。この技術を適切に使うことで、コードの重複を劇的に減らし、保守性の高い柔軟なシステムを構築することが可能になります。今回は、単なる継承の枠を超え、現代的なJava設計で不可欠なインターフェースの進化についても解説します。

基礎知識

継承には大きく分けて2つの形態があります。
1. クラス継承(extends Class): 親クラスのフィールドやメソッドを引き継ぎます。Javaは単一継承(親は一つ)のみ許可されています。
2. インターフェース継承(extends Interface): インターフェース同士を継承させ、型の定義を拡張します。インターフェースは複数継承が可能です。

また、Java 8以降のdefaultメソッドによって、インターフェースにも実装を持たせることが可能になりました。さらに、Java 9で導入されたprivate interface methodsにより、インターフェース内での共通処理を隠蔽できるようになり、より洗練された設計が可能になっています。

実装/解決策

継承を設計する際は「is-a関係(AはBの一種である)」が成立するかを常に意識してください。また、クラス継承よりもインターフェースによる抽象化を優先することで、結合度の低い、テストしやすいコードを書くことができます。

サンプルプログラム

import java.util.ArrayList;
import java.util.List;

// 共通機能を定義するインターフェース
interface Report {
void generate();

// デフォルトメソッド:実装クラスで共通のログ出力機能を提供
default void logStatus(String message) {
System.out.println(“[LOG]: ” + formatMessage(message));
}

// Java 9からのプライベートメソッド:内部処理を隠蔽し、コードの重複を排除
private String formatMessage(String msg) {
return “レポートシステム – ” + msg;
}
}

// クラス継承:基底クラス
class BaseReport {
protected String title;
public BaseReport(String title) { this.title = title; }
}

// クラス継承とインターフェース実装の組み合わせ
class PdfReport extends BaseReport implements Report {
public PdfReport(String title) { super(title); }

@Override
public void generate() {
logStatus(“PDF生成中: ” + title);
System.out.println(“PDFファイルを作成しました。”);
}
}

public class Main {
public static void main(String[] args) {
// 多態性(ポリモーフィズム)の活用
List reports = new ArrayList<>();
reports.add(new PdfReport(“2023年度決算資料”));

for (Report report : reports) {
report.generate();
}
}
}

応用・注意点

現場で最も注意すべきは「継承の乱用」です。継承は強力な結合を生むため、安易に深い階層を作ると変更に弱いコードになります。

  • 「継承」よりも「委譲(Composition)」を優先する設計を検討してください。
  • インターフェースのdefaultメソッドは、既存の実装を壊さずに機能追加できる強力な武器ですが、インターフェースの目的が「契約」であることを忘れず、実装を詰め込みすぎないようにしましょう。
  • 継承関係が深くなりすぎた場合は、設計を見直すサインです。シンプルさを保つことが、シニアエンジニアへの近道ですよ。

コメント

タイトルとURLをコピーしました