検索

キーワード


【Java】インターフェースとは?抽象クラスとの違いや書き方を解説

  • 公開日:2020-09-01 18:50:01
  • 最終更新日:2021-01-25 19:30:18
【Java】インターフェースとは?抽象クラスとの違いや書き方を解説

こんにちは、駆け出しプログラマーの若江です!

ここでは初学者として学習を終えた私が、アウトプットの意味も込めてインターフェースについて紹介させていただきます。

できる限り初学者が理解しやすい内容として紹介させていただくので、参考となれば幸いです!


関連記事リンク:継承とオーバーライドの紹介 / 定数の紹介 / コンストラクタの紹介 / メソッドの紹介 / インスタンスの紹介 / 抽象クラスの紹介 / アクセス修飾子の紹介 / final修飾子の紹介

インターフェースの使い方

インターフェースは処理内容が書かれていない(枠だけの)メソッドと定数のみを持った存在です。

枠だけを持つインターフェースのメソッドは最終的にクラスの中へ実装されて具体的な処理が書かれます。

本来メソッドはクラスへ直接書くことができるにも関わらず、

インターフェースを経由した、少し遠回りな書かれ方をするのにはどのような意味があるのか、

ここではインターフェースの役割やメリット、使い方について紹介させていただきます。


インターフェースの役割と書き方

インターフェースは具体的な処理を持たないメソッド(抽象メソッド)を持っています。

そのほかクラスが持つようなフィールド、コンストラクタなどをインターフェースは持ちません。

インターフェースの役割は、インターフェースが持つ「動作処理の無いメソッド」をクラスへ引き継いで、

クラスでメソッドの動作処理を確定させることです。

インターフェースをクラスへ引き継ぐことを「実装」と呼び、

インターフェースを実装したクラスは、インターフェースが持つメソッド全てに動作処理を書かなくてはなりません。


インターフェースの書き方

インターフェースの作成には interface を宣言します。

 ・インターフェース作成の基本構文: public interface インターフェース名{ メソッド; }


またインターフェースをクラスへ実装する際は implements を使います。

 ・インターフェース実装の基本構文: public class クラス名 implements インターフェース名 { 処理内容 }


◆インターフェース作成例 (interface)

public interface InterfaceTest {
}

◆上記インターフェースをクラスへ実装した例 (implements)

public class InterfaceTestImpl implements InterfaceTest {
}


インターフェースの仕事

メソッドには「クラス自身を動かすためのメソッド」と、

「クラスが他クラスへ提供するためのメソッド」の2種類があります。

例えば Object クラスが持つ toString メソッドなどが後者にあたりますが、

インターフェースのメソッドも後者の

「クラスが他クラスへ提供するためのメソッド」を実現させようとしています。

インターフェースは「規約」や「約束事」とも例えられるように、

インターフェース実装済みのクラスがどのようなメソッドを提供するか、

メソッドをどのように使うか、を伝える働きをします。


またインターフェース実装済みクラスが提供するメソッドを使うプログラマーは、

メソッドがどのような処理を行っているか、

その内容を気にすることなく利用できるようにする働きもします。


インターフェースと抽象クラスの違い

インターフェースとよく似た機能を持つものに「抽象クラス」があります。

抽象クラスの詳細は別記事で紹介させていただきますが、

インターフェースと同じように中身のないメソッド(抽象メソッド)を持つ事が出来るものが抽象クラスです。

また抽象クラスの抽象メソッドも、継承先のクラスで実際の処理内容を書くことが前提で作られています。

しかしインターフェースと違うところは、

抽象クラスの抽象メソッドは「継承先のクラス自身を動かすためのメソッド」を持っています。

抽象メソッドの実装が前提として抽象クラス全体が構成されているため、

抽象メソッドは継承先クラスで必ず実装しなければならい点で大きく異なります。

また抽象クラスはフィールドや動作処理の書かれた(具象)メソッドを持てる点でも、

インターフェースとは異なります。


余談

インターフェースを実装するクラスは、インターフェースが持つメソッドを全て実装しなくてはならないです。

見方を変えるとクラスが実装すべきメソッドをインターフェースが決めることもできます。

このような視点から「プログラム設計」の一部のような役割を果たす使い方も、

インターフェースの使い方としても考えられています。



インターフェースの特徴

先述した通りインターフェースにはメソッドの処理内容は書かずに枠だけを書きます。

・インターフェースのメソッド基本構文: public 戻り値の型 メソッド名(引数の型 引数名);


◆インターフェースのメソッド作成例

public interface InterfaceTest {

	public int num(int number);
}


他にも様々な特徴があるため紹介しておきます。

・メソッドのアクセス修飾子は public のみ:

 インターフェースのメソッドはクラスへの実装を目的に作られます。

 そのためインターフェースのメソッドは常にオープンな状態であり、

 public 以外のアクセス修飾子が設定できません。

 上記理由からインターフェースのメソッドの public は省略が可能となっています。 (インターフェースの定数も同様)

public interface InterfaceTest {

	int num(int number);
}

 またインターフェースのメソッドは抽象メソッドであり、暗黙的に abstract 修飾子が付与されていますが、

 abstract も public 同様省略可能で、実際に省略されているケースがほとんどです。


 ちなみにインターフェース自身が持つアクセス修飾子 public を省略した場合は、

 アクセス修飾子のデフォルト判定となり、同パッケージ内が有効範囲となるため注意しましょう。


・実装前提で作られるため final 宣言不可:

 上記同じ理由からインターフェースに final 修飾子は使用できません。



・インターフェースのフィールドは定数:

 先述した通りインターフェースは何か処理するような動作をしないためフィールドは変数を持ちません。

 ただし処理を必要としない public static final な定数を持つ事は可能です。

public interface InterfaceTest {
	int NUM = 1; // 定数 (public static final int NUM = 1; と同じ)

	int num(int number);
}



・多重継承ができる:

 こちらも先述しましたがインターフェースは実体を持ちません。

 メソッドに処理内容が書かれていないため、

 多重継承時に同名、別処理のメソッドとバッティングする心配がなく、多重継承が可能です。

 またクラス作成後に、後追いで新たなインターフェースを追加することも可能です。

【インターフェース1】

public interface InterfaceTest {
	int NUM = 1;

	int num(int number);
}

【インターフェース2】

public interface InterfaceTest2{

}

【多重継承したクラス】 implements の後にカンマ区切りでインターフェース名を記述する

public class InterfaceTestImple implements InterfaceTest, InterfaceTest2 {

}



・実装するクラスはインターフェースの全メソッドを実装する:

 インターフェースを実装したクラスは全てのメソッドの処理内容を実装しなければなりません。

 これは多重継承した場合も同じで、多重継承したインターフェースのメソッドは全て実装が必要です。


【インターフェース】

public interface InterfaceTest {

	int num(int number);
}

【実装クラス】 num メソッドを実装していないとエラーになる

public class InterfaceTestImple implements InterfaceTest{

	public int num(int num) {
		return num;
	}
}


 ただしインターフェースは抽象クラスへの実装も可能ですが、

 抽象クラスではインターフェースのメソッドの実装が必須ではありません。

 (最終的に抽象クラスを実装する具象クラスでは、メソッドの処理内容を実装しなくてはなりません。)



・インターフェース同士の継承ができる:

 インターフェース同士は継承関係を持つことができます。

public interface InterfaceTest2 extends InterfaceTest {
}

 ※継承の方法、その目的はクラスの継承と同じです。


余談

インターフェースを実装したクラス名の末尾によく「Impl」が付いていることがあります。

これは「implements」の先頭4文字を取っていて、

インターフェースを実装したクラスの目印として使われています。

どこかで「クラス名Imple」を見かけたときは、インターフェースを実装しているんだなと思ってください。



インターフェースでの instanceof

インターフェースを実装したクラスをインスタンス生成するときに、

実装したインターフェースを型にした変数を作成することができます。

このインターフェースを型として持った変数に instanceof を使った場合に限り、

インスタンス生成したクラスに紐づいている全てのインターフェースを調べることができます。

実際にサンプルコードで確認してみましょう。


【インターフェース1】 クラスへ実装するインターフェース

public interface InterfaceTest {
}

【インターフェース2】 クラスへ実装するインターフェース

public interface InterfaceTest2 {
}

【インターフェース3】 クラスへ実装しないインターフェース

public interface InterfaceTest3 {
}

【実装クラス】 InterfaceTest と InterfaceTest2 を実装

public class InterfaceTestImpl implements InterfaceTest, InterfaceTest2{
}

【実行クラス】 instanceof でインターフェース型の変数 test が実装している他のインターフェースを調べる

public class Test {

	public static void main(String[] args) {

		InterfaceTest test = new InterfaceTestImpl();

		System.out.println(test instanceof InterfaceTest); // 結果:true を表示
		System.out.println(test instanceof InterfaceTest2); // 結果:true を表示
		System.out.println(test instanceof InterfaceTest3); // 結果:false を表示
	}
}


それぞれの関係を説明します。

※流れを追いやすくするために色分けしています。

▶「InterfaceTestImplクラスは、

 「InterfaceTestインターフェースとInterfaceTest2インターフェースを実装しています。

ちなみにInterfaceTestImplクラスが実装した、

 「InterfaceTestInterfaceTest2は別々のインターフェースのため関連性がありません。

▶「InterfaceTestImplクラスをインスタンス化する際の型をInterfaceTest型、変数名testにしました。

▶「InterfaceTest型のtestが実装したインターフェースが何かをinstanceofで調べています。

▶「InterfaceTestInterfaceTest2に関連性はないですが、結果にtrueが返ってきます。

一方InterfaceTestImplInterfaceTest3は実装していないためfalseが返ってきます


つまりInterfaceTestInterfaceTest2がお互いに知り合いじゃなくても、

InterfaceTestImplクラスと他のインターフェースの関係性を調べることができます。

この機能のメリットは、InterfaceTestImplクラスが使える(インターフェース実装の)メソッドが

何かを調べることができるという点です。



関数型インターフェースの紹介

Java8 からインターフェースの種類として新たに「関数型インターフェース」が導入されました。

関数型インターフェースは、ラムダ式やメソッド参照で使用するために導入されています。

ラムダ式ではメソッドの記述が省略されるため、

関数型インターフェースで省略されたメソッドを指定してあげているという関係にあります。

そのため関数型インターフェースは、抽象メソッドを一つのみ持つインターフェースという特徴があります。


【関数型インターフェース】

public interface Sample {
	public abstract void sample(String str); // 1つの抽象メソッド
}

【インスタンス生成クラス】

public class Sample2 {
	public static void main(String[] args) {

		Sample test = text -> System.out.println(text); // インスタンス生成 + ラムダ式
		test.sample("関数型インターフェースの紹介");
	}
}


ラムダ式の知識が必要となってきますので、ここまでの紹介とさせていただきたいと思います。

ラムダ式に関しては別記事で詳しく紹介させていただきます。



まとめ

インターフェースはオブジェクト指向ならではの機能を持っているため、

概念の理解が少し難しいかもしれませんが、Java を学ぶ上では必須の知識となりますので理解しておきましょう。

Java8 よりインターフェースに機能実装された default と static についても別記事で紹介させていただきます。

知識に余裕があればぜひ読んでみてください。


関連記事リンク

継承とオーバーライドの紹介 / 定数の紹介 / コンストラクタの紹介 / メソッドの紹介 / インスタンスの紹介 / 抽象クラスの紹介 / アクセス修飾子の紹介 / final修飾子の紹介


【著者】

若江

30代で異業種となるIT業界へ転職した駆け出しのプログラマです。これまで主に Java や Ruby、HTML/CSS を使って学習を目的としたショップサイトや掲示板サイトの作成を行いました。プログラマとしての経験が浅いからこそ、未経験者の目線に近い形で基礎の紹介をしていきたいと思います。

よく読まれている記事
【Java】JSPでタグライブラリを使う(JSTL)

【Java】JSPでタグライブラリを使う(JSTL)

こんにちは。エンジニアの新田です!ここでは、システムエンジニアとして働いている私が、システム開発手法や開発言語について紹介していこうと思います。今回は、JSPの標準タグライブラリ「JSTL」について紹介します。Javaについて勉強している方、Webアプリケーションを構築したいと思っている方の参考になれば幸いです!関連記事リンク: 【Java】JSPの基本的な構文/【Java】JSPのアクションタグ

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

【Java】Stringクラス文字列を操作するメソッドの使い方まとめ!実例も紹介!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!そもそもStringとは何?『 String 』... Java言語において文字列のデータ型を指します。基本デ

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

【Java】文字列の置き換え(String#format)!エスケープシーケンスのまとめも!!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!Stringクラスformatメソッドの文字列整形【java.utilパッケージ】Formatterクラスfo

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

【Java】文字列格納後に変更可能!?StringBufferクラスとStringBuilderクラス!

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者にも✅、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!文字列を扱う3つのクラス【java.langパッケージ】java.langパッケージの文字列を扱うクラスにはS

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

【Java】値?変数?型??しっかり解説!『データ型(プリミティブ型と参照型)』

こんにちは。新人エンジニアのサトウです。システムエンジニアとして駆け出したばかりですが、初心者なりの視点でわかりやすい記事を心がけていますので参考になればうれしいです。プログラム初心者✅にも、プログラムに興味がある人✨も、短い時間で簡単にできますのでぜひこの記事を読んで試してみてください!プリミティブ型と参照型プログラム開発では型を持った変数を使ってデータのやり取りをしますが、データ型によって仕様