目次
implementsとは
「implements」キーワードはJavaでインターフェース(interface)を実装する時に使用すキーワードです。
と言ってもピンとこない人が多いと思います。implementsの前に、Javaのインターフェース(interface)について知っておく必要があるため、先にインターフェイスの説明をします。
インターフェース(interface)とは
インターフェースとはある機能を実現するための機能を抽出したもので、よくインターフェースは「契約」や「約束」と言われることが多いです。
具体的には抽象メソッドのみで構成されるファイルで、中身の処理はありません。Javaではインターフェースに定数を指定したメンバ変数も宣言できます。
実際にインターフェースのサンプルコードを見てみましょう。
public interface インタフェース名 { //メンバ変数(定数) public int NUM1 = 3; //メソッド(宣言のみ) void method1(); int method2(); }
上の例を見ても分かる通り、インターフェイスにはメソッドの定義だけを行い、中身の処理がないため、そのままでは使用できません。そのため、インタフェースはクラスに実装して使用します。
implementsはインターフェースの実装
先述したように、インタフェースはクラスに実装して使用します。そこで「implements」キーワードが出現です。implementsはインタフェースをクラスに実装するときに使用します。
implementsの構文
早速、implementsを使ってインタフェースを実装する例を見てみましょう。以下のインターフェースを用意して、実際にクラスに実装していきましょう。
public interface Stopwatch { void start(); void stop(); void pause(); }
上のインターフェースを実装したものが、次のサンプルコードです。
implementsキーワードの横に、実装するインターフェース名を指定します。また、インターフェースを実装するメソッドに@Overrideアノテーションを付けてメソッドをオーバーライドしています。
`
public class StopwatchImpl implements Stopwatch {
@Override
public void start() {
System.out.println("開始");
}
@Override
public void stop() {
System.out.println("停止");
}
@Override
public void pause() {
System.out.println("一時停止");
}
}
複数のインターフェースを実装
クラスに複数のインターフェースを実装する場合は、implementsキーワードの横に、実装するインターフェース名をカンマ区切りで指定します。そして、指定したインターフェースのメソッドをすべてクラスに実装します。
次のサンプルコードは、Interface1とInterface2を、Sampleクラスに実装した例です。
public interface Interface1{ void method1(); void method2(); } public interface Interface2{ void method3(); } public class Sample implements Interface1, Interface2 { @Override public void method1() { System.out.println("method1"); } @Override public void method2() { System.out.println("method2"); } @Override public void method3() { System.out.println("method3"); } }
継承とインターフェースの違い
継承
クラスの継承は、継承元はスーパークラス(親クラス)の1つに限ります。しかし、インターフェースにはそういう制限はなく、複数のインターフェースを実装できます。
まは、継承は親のクラスの機能を継承して、必要な部分のみを拡張するという考え方で、親の実装を継承したクラスで改めて記述する必要がないため、一般的にコードの記述量の削減に繋がる機能です。
インターフェース
継承が機能の拡張なのに対し、インターフェースの役割は、ふるまいの共通化です。例えば音楽プレイヤーと、DVDプレイヤーの例で考えてみましょう。それぞれ「再生」「停止」「早送り」「巻き戻し」などの機能が共通していますが中の処理が全く違うため、同じコードは使えません。
もし両方の機器を操作できるリモコンを開発するとき、音楽プレイヤーと、DVDプレイヤーでクラスのメソッド名や引数が異なっていると、リモコンの開発側は機器毎に処理を分けて実装する必要があり、コーディング量が増え、処理も煩雑になります。
そこでplay, stop, forward, backwardなどの共通のメソッドを定義したインターフェースを作り、音楽プレイヤーと、DVDプレイヤーはそのインターフェース実装することで、リモコン側は操作する機器のクラスのインスタンスを切り替えるだけで、まったく同じソースコードで2つの機器を操作できます。
このような考え方は、DI(依存性の注入)を行うSpring Framewordでも用いられています。
Java8からのインターフェース変更点
default(デフォルト)メソッド
Java8からはdefault(デフォルト)メソッドと呼ぶ機能が追加され、インターフェースにも実装を持つことができるようになりました。
以下のサンプルコードは、実際にデフォルトメソッドを定義したサンプルコードです。インターフェイスなのに、sample1メソッドに中身の処理が実装されているのが分かると思います。
//default(デフォルト)メソッドを定義したインターフェース interface DefaultInterface { default public void sample1() { System.out.println("これはデフォルトメソッドです。"); } }
Java7までは、インターフェイスで定義されたメソッドはすべて実装する必要がありましたが、デフォルトメソッドについては、オーバーライドが必須ではありません。オーバーライドしなかった場合、インターフェイスに記述したデフォルトメソッドの内容がクラスに実装されます。
defaultメソッドの使用例
実際に上の例で作成したDefaultInterfaceインターフェースを、実装したのが、次のMyClassです。デフォルトメソッドであるsample1が定義されていません。この状態でもコンパイルエラーにはあなりません。
public class MyClass implements DefaultInterface { public static void main(String[] args) { MyClass cls = new MyClass(); cls.sample1(); } }
上のMyClassを実行すると、次のようにデフォルトメソッドの内容が実装され、コンソールに次のように表示されます。
これはデフォルトメソッドです。
defaultメソッドをオーバライドすれば処理が上が書ける
defaultメソッドは、これまでのインターフェース同様に、実装するクラス側でオーバーライドできます。オーバーライドすることで、defaultメソッドの処理内容を上書きできます。
次の例は、DefaultInterfaceのdefaultメソッドを、MyClass側でオーバーライドした例です。
public class MyClass implements DefaultInterface { public static void main(String[] args) { MyClass cls = new MyClass(); cls.sample1(); } @Override public void sample1() { System.out.println("これはMyClassのメソッドです。"); } }
MyClassを実行すると、次のようにオーバーライドした方の処理が実行されるのが分かります。
これはMyClassのメソッドです。
まとめ
インターフェース(interface)と、implementsの使い方について説明してきました。インターフェースを用いた開発は、Javaの開発では一般的に用いられています。この機会に覚えておきましょう。
- implementsはクラスにインターフェースを実装する時に使う
- 継承は機能の拡張、インターフェース(interface)はふるまいの共通化
- Java8からはdefaultメソッドを使ってインターフェースに実装が書ける