【Java OOP】interfaceとは?実装(implements)で学ぶ「振る舞いの契約」
公開日: 2025年10月19日
Javaのオブジェクト指向を学んでいると、extends(継承)と並んで必ず登場するのが implements(実装)というキーワードです。 そして、implements と共に現れるのが interface(インターフェース)という謎の存在。 「クラスと似ているけど、何が違うんだろう?」「extendsがあるのに、なぜimplementsも必要なの?」 そんな疑問を抱いたことはありませんか?
結論から言うと、インターフェースは「クラスが遵守すべき、振る舞いの契約書」であり、Javaが単一継承しかできないという制約を乗り越えるための、エレガントな解決策なのです。
今日は、このインターフェースという強力な概念を、「テレビのリモコン」という身近な例えを使って、その本質から解き明かしていきます。
🤔 問題点:extends(継承)だけでは世界は表現できない
まず、なぜinterfaceが必要なのかを知るために、extendsだけが持つ限界を見てみましょう。 Javaのクラスは、たった一つの親クラスしかextends(継承)できません(これを単一継承と言います)。 例えば、DogクラスはAnimalクラスを継承できますが、同時にRobotクラスを継承して「ロボット犬」になることはできません。
しかし、世の中には「Aであり、かつBでもある」という性質を持つものはたくさんあります。 「犬」や「猫」はAnimalであると同時に、「ペット」でもあります。「スマートフォン」や「ドローン」はMachineであると同時に、「充電可能(Chargable)」なものでもあります。 この「〜できる」という能力や振る舞いを、クラスの親子関係とは別に表現する仕組みが必要なのです。
📺 解決策:interfaceという「リモコンの設計図」
インターフェースとは、メソッドの具体的な処理は一切書かず、メソッド名、引数、戻り値の型だけを定義した「機能のリスト」です。 これは、ボタンの配置だけが決まっている「リモコンの設計図」によく似ています。
// 「リモコン」というインターフェース(契約書)を定義
public interface RemoteControl {
// このインターフェースを実装するクラスは、
// 以下の3つの機能を必ず持たなければならない、と約束させる。
void powerOn(); // 電源を入れる機能
void volumeUp(); // 音量を上げる機能
void volumeDown(); // 音量を下げる機能
}
💡【重要】extends と implements の違い
extends は「is-a」の関係(犬は動物である)を表す継承です。親子関係であり、子は親の資産(フィールドやメソッド)を引き継ぎます。
implements は「can-do」の関係(テレビは電源オンできる)を表す実装です。契約関係であり、そのクラスが特定の「能力」を持っていることを保証します。
🛠️ 実装:implementsで契約を履行する
このRemoteControlインターフェースを使って、具体的なテレビのクラスを作ってみましょう。 インターフェースをimplementsしたクラスは、そのインターフェースで定義された全てのメソッドを、具体的な処理({...})と共に実装する義務を負います。
// Sony製のテレビクラス
class SonyTV implements RemoteControl {
private int volume = 10;
@Override
public void powerOn() {
System.out.println("SONY: Power ON. Welcome!");
}
@Override
public void volumeUp() {
volume++;
System.out.println("SONY: Volume -> " + volume);
}
@Override
public void volumeDown() {
volume--;
System.out.println("SONY: Volume -> " + volume);
}
}
// Samsung製のテレビクラス
class SamsungTV implements RemoteControl {
private int volumeLevel = 5;
@Override
public void powerOn() {
System.out.println("Samsung TV: Turning on...");
}
@Override
public void volumeUp() {
volumeLevel += 2; // Samsungは音量が2ずつ上がる
System.out.println("Samsung TV: Current Volume is " + volumeLevel);
}
@Override
public void volumeDown() {
volumeLevel -= 2;
System.out.println("Samsung TV: Current Volume is " + volumeLevel);
}
}
SonyTVもSamsungTVも、同じRemoteControl契約を履行していますが、その中身の実装は全く異なります。これがインターフェースの強力な点です。
✨ インターフェースの真価:ポリモーフィズム
インターフェースが本当に輝くのは、ポリモーフィズム(多態性)と組み合わせた時です。 `RemoteControl`という「型」として、SonyTVもSamsungTVも同じように扱うことができるのです。
public class LivingRoom {
public static void main(String[] args) {
// リモコン(インターフェース型)の変数に、
// SonyTV(実装クラス)のオブジェクトを入れる
RemoteControl sonyRemote = new SonyTV();
// 同じく、SamsungTVのオブジェクトも入れられる
RemoteControl samsungRemote = new SamsungTV();
// 操作する側は、中身がSony製かSamsung製かを知る必要がない
// ただ「リモコン」として、契約されたボタンを押すだけ
operateTV(sonyRemote);
System.out.println("---");
operateTV(samsungRemote);
}
// 引数で「リモコン」というインターフェースを受け取るメソッド
public static void operateTV(RemoteControl remote) {
remote.powerOn();
remote.volumeUp();
remote.volumeUp();
remote.volumeDown();
}
}
operateTVメソッドは、中身が何であろうとRemoteControlインターフェースを実装していることさえ知っていれば、安心してpowerOn()やvolumeUp()を呼び出すことができます。 将来、PanasonicTVという新しいクラスができても、operateTVメソッドを一切変更する必要はありません。これこそが、疎結合で、拡張性の高い、美しい設計なのです。
まとめ
インターフェースは、Javaのオブジェクト指向を支える、非常に強力でエレガントな仕組みです。
- interfaceは、実装すべきメソッドを定義した「契約書」である。
- クラスはimplementsキーワードで、複数のインターフェースが持つ「能力」を実装できる。(多重継承の代替)
- インターフェースを型として使うことで、ポリモーフィズムが実現でき、柔軟で拡張性の高いコードが書ける。
extendsが「血の繋がり」を表すなら、implementsは「資格や免許」を表します。 この2つの関係を正しく理解し、使い分けることができた時、あなたのJavaの設計スキルは、間違いなく次のレベルへと到達するでしょう。
プログラミング学習に必須ツール!
記事で紹介したコードがよく分からなかったり、ご自身のコードについてもっと知りたい場合は、AIコード解説ツールが便利です。コードを貼り付けるだけで、AIが日本語で分かりやすく解説します。
AIコード解説ツールを使ってみる →