Javaのimplementsとは?インターフェース実装・extendsとの違い・実務活用まで徹底解説
CONTENTS
Javaの学習を進めると、class A implements B という構文に必ず直面します。しかし、多くの初心者がここで疑問を抱くのも事実です。
「継承(extends)と何が違うの?」
「なぜわざわざインターフェースを実装するの?」
このように感じるのは、implements が単なる「機能の継承」ではなく、「設計の契約」という意味合いが強いからです。
そこで本記事では、implements の基本的な構文から、抽象クラスとの明確な違い、そして現場で必須となる「疎結合な設計」への応用までを体系的に解説します。
implementsの基本:インターフェースを契約として扱う
まず結論から言えば、インターフェースとは「このクラスは、必ずこのメソッドを持っています」という契約書のようなものです。そして、その契約を守る(実装する)ためのキーワードが implements です。
具体的には、以下のような役割分担になります。
- interface(インターフェース):メソッドの型(名前や引数)だけを定義し、中身は書かない(仕様書)
- implements(実装):インターフェースで定義されたメソッドの中身を具体的に記述する(製造)
例えば、「動物(Animal)」というインターフェースを定義してみましょう。
基本的なコード例
まず、インターフェースを定義します。「鳴く(speak)」という機能を持つことを強制する仕様です。
// インターフェース定義
public interface Animal {
// 具体的な処理は書かず、型だけ宣言する
void speak();
}
次に、このインターフェースを implements を使って実装します。
// インターフェースを実装するクラス
public class Dog implements Animal {
@Override
public void speak() {
// ここで初めて具体的な処理を書く
System.out.println("ワン!");
}
}
public class Cat implements Animal {
@Override
public void speak() {
System.out.println("ニャー!");
}
}
このように、implements Animal と宣言したクラスは、必ず speak() メソッドを実装しなければなりません。もし実装し忘れると、コンパイルエラーが発生します。
参考リンク:Oracle公式 Java インターフェース解説
implementsを使う3つの明確なメリット
では、なぜ直接クラスにメソッドを書かず、わざわざインターフェースを経由するのでしょうか。主な理由は以下の3点です。
- 実装の強制(契約の保証)
「メソッド名の書き間違い」や「実装漏れ」を防ぎ、チーム開発での規格を統一できます - 多重実装が可能
Javaのクラス継承(extends)は1つしかできませんが、インターフェースは複数実装(implements A, B)が可能です - ポリモーフィズム(多態性)の実現
「犬」も「猫」も、プログラム上は同じ「動物(Animal)」として扱えるようになります
特に3つ目の「ポリモーフィズム」は重要です。以下のように、異なるクラスを同一の型として処理できます。
Animal myDog = new Dog();
Animal myCat = new Cat();
// どちらもAnimal型として扱える
myDog.speak(); // "ワン!"
myCat.speak(); // "ニャー!"
インターフェースと抽象クラスの違い
一方で、よく混同されるのが「抽象クラス(abstract class)」です。どちらも「抽象メソッド」を持てますが、役割と制約が異なります。
以下の表で主な違いを整理しました。
| 項目 | インターフェース (interface) | 抽象クラス (abstract) |
|---|---|---|
| 目的 | 機能の「契約」を定義する (CAN-DOの関係) |
共通処理の「ひな形」を作る (IS-Aの関係) |
| 多重継承 | 可能 (implements A, B) | 不可 (extendsは1つのみ) |
| フィールド | 定数のみ (static final) | 通常の変数も保持可能 |
| メソッド | 基本は抽象メソッド (Java8以降 default可) |
通常メソッドと抽象メソッドを混在可 |
したがって、使い分けの基準は以下のようになります。
- interface:クラスの階層に関係なく、「機能」を付与したい場合(例:
Runnable,Serializable) - abstract class:親子関係があり、基本動作を共通化したい場合(例:
BaseService)
実務的な使い方とDI(依存性注入)
ここからは、現場レベルでの活用法を見ていきましょう。実務では、implements は「疎結合(Loose Coupling)」を実現するために不可欠です。
特に Spring Boot などのフレームワークでは、DI(依存性注入)と組み合わせて頻繁に使用されます。
通知サービスの設計例
例えば、ユーザーへの通知機能を開発するとします。最初はメール通知だけだったとしても、将来的にLINEやSlack通知が増える可能性があります。
そこで、具体的なクラスに依存せず、インターフェースに依存するようにコードを書きます。
// 1. 共通インターフェース
public interface NotificationService {
void send(String message);
}
// 2. メールでの実装
public class EmailService implements NotificationService {
public void send(String message) {
System.out.println("Email送信: " + message);
}
}
// 3. LINEでの実装
public class LineService implements NotificationService {
public void send(String message) {
System.out.println("LINE送信: " + message);
}
}
利用側のコード(ビジネスロジック)
重要なのは、通知を利用する側のクラスが、EmailService や LineService を直接知らなくて良い点です。
public class UserManager {
// 具体的なクラスではなく、インターフェース型で保持する
private final NotificationService notifier;
// コンストラクタで実装を受け取る(DI)
public UserManager(NotificationService notifier) {
this.notifier = notifier;
}
public void registerUser() {
// 具体的な手段(メールかLINEか)を気にせず実行できる
notifier.send("ユーザー登録完了");
}
}
このように設計しておけば、「メール通知からLINE通知に切り替えたい」という場合でも、UserManager のコードを一切修正する必要がありません。渡す実装クラスを変えるだけで済むからです。
この「変更に強い性質」こそが、実務でインターフェースが重宝される最大の理由です。
参考リンク:Spring Framework Documentation (IoC Container)
Java 8以降のdefaultメソッドについて
さらに、近年のJava開発では知っておくべき機能があります。Java 8から導入されたdefaultメソッドです。
以前のインターフェースは「実装を持つことができない」のが常識でしたが、defaultキーワードを使うことで、インターフェース内に初期実装を持てるようになりました。
public interface Logger {
void log(String msg);
// 共通の実装を提供できる
default void logError(String msg) {
log("ERROR: " + msg);
}
}
これにより、既存のインターフェースに新しいメソッドを追加しても、実装クラス側でコンパイルエラーにならずに済むようになり、ライブラリの互換性維持が容易になりました。
まとめ:インターフェースは変更に強いコードの鍵
本記事では、Javaの implements の仕組みと、実務での活用ポイントを解説しました。
- 契約の定義:メソッドの実装を強制し、クラスの規格を統一する
- 多重実装:複数の役割を1つのクラスに持たせることができる
- 疎結合の実現:DIと組み合わせることで、変更やテストに強い設計になる
最初は「コード量が増えるだけでは?」と感じるかもしれませんが、規模が大きくなるにつれて、インターフェースによる設計の恩恵を強く感じるはずです。まずは小さなプログラムで、クラスを直接使うのではなくインターフェース経由で操作する書き方を練習してみてください。
さらに、実務レベルのJava設計やDIの仕組みを深く理解したい場合は、プロのエンジニアによるコードレビューを受けながら学習を進めるのが近道です。
つまずいたら、現役エンジニアと一緒に解決しよう
この記事で扱った【Java】は、独学だと細部で詰まりやすい分野です。さらに理解を深めたい方は、Zerocode Onlineで実務直結の学習を進めてみませんか。
コード添削・詰まり解消を丁寧にサポート。
Java/SQL/Spring Bootを体系的に習得。
現場で刺さる成果物づくりを伴走。
時間と場所を選ばず学べます。