Javaのオブジェクト指向を学ぶ上で欠かせない「インターフェイス」。
でも、「インターフェイスって何?」と悩む初心者も多いはず。
本記事では、インターフェイスの基礎から具体例、メリット、抽象クラスとの違いまでを図解を交えて徹底解説します!
この記事を読めば、「なぜJavaでインターフェイスを使うのか」がスッキリ理解できるはずです。
Javaのインターフェイスを完全理解するために
Javaのオブジェクト指向を理解する上で、「インターフェイス」について理解することは避けて通れません。
ただ、Javaの初心者にとって、「インターフェイス」とは何かがいまひとつピンとこない場合が多いでしょう。その理由の一つとして、この「インターフェイス」をクラス設計に用いるメリットが明確に理解されていないことが挙げられます。
そこで本記事では下記の内容を中心に、「Javaのインターフェイスとは?」に関して図解付きで徹底解説!
- Javaの「インターフェイス」とは
- Javaの「インターフェイス」を用いるメリット
- 「抽象クラス」と「インターフェイス」の違い
本記事を最後まで読んでいただくことで、その場だけの知識ではなく、「なぜJavaでインターフェイスを用いるのか」という深い理解につなげることができます。
Javaのインターフェイスをわかりやすく解説!
インターフェイスの基本概念と活用例
Javaでの「インターフェイス」とは、実装関係にあるクラスが持つべきメソッドを定めたクラス設計方法です。
インターフェイスで抽象メソッドを宣言し、その具体性な処理は実装されたクラス側で完成させます。
これにより、実装関係にあるクラスの共通の型ができ、クラスを一元的に操作することを可能にします。
例:
// インターフェイスを定義
public interface Moveable {
// 定数
String msg = "移動手段"
// 抽象メソッド
void showDistance(); // ※ 暗黙的に「public abstract」
}
// スーパークラスを定義
class Transportation {
String name; // メンバ変数
// コンストラクタ
Transportation(String name) {
this.name = name;
}
}
// 「実装クラス」かつ「サブクラス」であるクラスを定義
class Train extends Transportation implements Moveable {
private int distance; // メンバ変数
// コンストラクタ
Train(String name, int distance) {
super(name);
this.distance = distance;
}
@Override
// オーバーライド元と同様のpublicの修飾子である必要があるため、public指定必須
public void showDistance() {
System.out.println(Moveable.msg);
System.out.println(name + " : " + distance + "km");
}
}
インターフェイスで何が宣言できる?
- 抽象メソッド(暗黙的に「public abstract」)
- 「public」なのは、実装クラスにおいて具体性な処理内容がオーバーライドされる前提のため
- 定数(暗黙的に「public static final」)
- インスタンス変数は持たず、実装クラスで共通に使用する定数となる。final指定のため、宣言時に明示的な初期化が必要。
- 以下の具象メソッド(※詳細は割愛します)
- defaultメソッド(Java8以降)
- staticメソッド(Java8以降)
- privateメソッド(Java8以降)
インターフェイスの注意点まとめ
- インターフェイス同士で継承することができる
- 実装クラスにおいては、複数のインターフェイスを実装することができる
- インターフェイスは実装(implements)される前提のため、finalにはできない
- 実装クラスにおけるオーバーライドメソッドにおいては、オーバーライド元と同じ範囲の修飾子となる必要があるため、public指定必須
public interface Hoge {
void sampleMethod();
}
// インターフェイス同士で継承することができる
public interface Fuga extends Hoge {}
// インターフェイスは複数を実装することができる
public class Piyo implements Hoge Fuga {}
// コンパイルエラー:実装(implements)される前提のため、finalにはできない
// public final interface Piyo {}
public class HogeHoge implements Hoge {
@Override
// オーバーライド元と同様のpublicの修飾子である必要があるため、public指定必須
public void sampleMethod() {
System.out.println("オーバーライドしたよ");
}
}
Javaのインターフェイスを使うメリットとは?
重要なメソッドの実装漏れを防ぐ
インターフェースが持つ抽象メソッドは、実装クラスが「何をすべきか」を定義します。
実装の詳細には触れず、どのクラスでも同じメソッドを持つことを保証するため、重要なメソッドの実装漏れを防ぐことができます。
多重継承の代わりとなる
Javaではクラスの多重継承はできませんが、インターフェースは複数実装可能です。
異なる機能を持つインターフェースを組み合わせることで、柔軟な設計が可能になります。
柔軟性と拡張性の向上
インターフェースを1つ作ってしまえば、実装を変更しても外部に影響を与えません。
実装を差し替えたり、異なる実装を簡単に扱うことができます。
ポリモーフィズムの活用
「ポリモーフィズム(多様性)」は、同じ操作の呼び出しで、オブジェクトごとに異なる動作を実現することです。オブジェクト指向において重要な概念になります。
例:
/**
* あくまで、Fruitsクラスを継承or実装している各クラスが存在しており、
* eatIt()というメソッドをそれぞれ異なる処理内容でオーバーライドしているという想定です。
*/
public class Main {
public static void main(String[] args) {
Fruits[] fruits= { new Apple(), new Banana(), new Mango(), new Grapes() };
// f.eatIt()でポリモーフィズムを実現したメソッドアクセス
// 配列内の各共通のeatIt()にアクセス(毎回のループで参照するオブジェクトが切り替わる)
for (Fruits f : fruits) {
System.out.println(f.eatIt());
}
}
}
あくまで想定の範囲ではありますが、eatIt()というメソッドをそれぞれ異なる処理内容でオーバーライドしているため、1つの呼び出しによって、異なる処理が行われる形になります。
よくある質問(FAQ)
Q: 「抽象クラス」と「インターフェイス」の違いは何ですか?
Javaにおいて「抽象クラス」と「インターフェース」は、どちらもクラスに共通の機能を持たせる仕組みですが、それぞれ目的や使い方が異なります。以下でその違いを具体例とともに解説します。
1. 定義と役割の違い
- 抽象クラス:
クラス間で共通の性質や動作をまとめるために使用します。
一部のメソッドを具体的に実装できるため、サブクラスで共通の振る舞いを継承させることができます。 - インターフェース:
クラス間で共通のルールを定義します。
実装の詳細には触れず、複数の異なるクラスで共通の振る舞いを保証することが目的です。
2. コード例で比較
【抽象クラスの例】
「動物」という概念を表すAnimal
抽象クラスを定義します。このクラスはすべての動物が共有する**フィールド(名前)や具体的な動作(sleep()
メソッド)**を持ちつつ、鳴き声(makeSound()
メソッド)はサブクラスに委ねます。
abstract class Animal {
String name; // 共通のフィールド
Animal(String name) {
this.name = name;
}
// サブクラスで実装すべき抽象メソッド
abstract void makeSound();
// 具体的なメソッド
void sleep() {
System.out.println(name + " is sleeping");
}
}
class Dog extends Animal {
Dog(String name) {
super(name);
}
@Override
void makeSound() {
System.out.println(name + " says: Woof!");
}
}
使用例:
Animal dog = new Dog("Buddy");
dog.makeSound(); // 出力: Buddy says: Woof!
dog.sleep(); // 出力: Buddy is sleeping
【インターフェースの例】
「飛ぶ能力」を表すFlyable
インターフェースを定義します。このインターフェースを実装するクラスには、fly()
メソッドを必ず実装させます。
interface Flyable {
// 抽象メソッド
void fly();
// デフォルトメソッド(Java 8以降)
default void land() {
System.out.println("Landing...");
}
}
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying");
}
}
class Plane implements Flyable {
@Override
public void fly() {
System.out.println("Plane is flying");
}
}
使用例:
Flyable bird = new Bird();
bird.fly(); // 出力: Bird is flying
bird.land(); // 出力: Landing...
Flyable plane = new Plane();
plane.fly(); // 出力: Plane is flying
3. 違いを表で比較
抽象クラス | インターフェース | |
主な役割 | 共通の性質や動作を持たせる | 共通のルールを定義する |
継承の制限 | 単一継承のみ | 複数のインターフェースを実装可能 |
メソッド | 具体的・抽象的なメソッドを定義可能 | 抽象メソッド、デフォルト・静的メソッドを定義可能 |
フィールド | インスタンス変数を持てる | 定数(static final )のみ持てる |
使用例 | 共通の振る舞いを持つクラスの基盤 | 異なるクラス間の共通の振る舞いを統一する |
4. 使い分けのポイント
- 抽象クラスを選ぶ場面
- 共通のフィールドや具体的なメソッドを持たせたいとき。
- 継承階層でサブクラスの基本的な動作を定義したいとき。
- インターフェースを選ぶ場面
- 実装の詳細を隠しつつ、異なるクラスで共通のルールを実現したいとき。
- クラスが複数の役割を持つ必要があるとき。(多重実装)
おわりに
- Javaの「インターフェイス」とは
- 実装関係にあるクラスが持つべきメソッドを定めたクラス設計方法
- Javaの「インターフェイス」を用いるメリット
- 重要なメソッドの実装漏れを防ぐ
- 多重継承の代わりとなる
- 柔軟性と拡張性の向上
- ポリモーフィズムの活用
- 「抽象クラス」と「インターフェイス」の違い
- 抽象クラス:共通の性質や動作を共有するのに適している。
- インターフェイス:異なるクラス間で共通のルールを定めるために使います。