Javaでオブジェクト指向を勉強を初めた初心者にとって、
implementsって何のためにあるの?
と疑問に思ってしまう方も多いのではないでしょうか?
でも、使い方がわかると後々で柔軟に対応がとれるようになるので、けっこう便利なんです。
そこで、この記事では
- 【基礎】interfaceの使い方
- 【発展】interfaceとdefaultの使い方
- 【発展interfaceとstaticの使い方
- 【発展】interfaceとabstract(抽象クラス)との違い
などの基礎から応用的な内容についても解説していきます。
今回はinterfaceやimplementsについて、使い方をわかりやすく解説します!
なお、Javaの記事については、こちらにまとめています。
interfaceの使い方
interfaceでは、定数とメソッド名のみ定義できます。
定義する変数は「public static final」が付いているものとみなされ、定数として扱われます。
また、実装したクラスではメソッドの実装が必須となります。
interfaceの宣言と実装について
インターフェースの宣言は下記のように記述します。
インターフェースの宣言例:
interface インターフェース名 { メンバー変数の定義; メンバーメソッドの型の定義; }
インターフェースを実装する場合には「implements」句を使用し下記のように記述します。
インターフェースの実装例:
class クラス名 implements インターフェース名 { ・・・ }
メソッドを実装する方法
それではサンプルコードでメソッドを実装する方法についてみていきましょう。
//インターフェースの宣言 interface Calc1{ //メンバ変数(定数) public String STR = "足し算"; public int A = 3; public int B = 6; //メソッド(型のみ宣言) void method1(); void method2(String str); void method3(); } //インターフェースの実装 class Add implements Calc1{ // メソッドの実装 public void method1() { System.out.println(STR + "をします"); } public void method2(String str) { System.out.println(str + "をします"); } public void method3() { System.out.println("計算結果: " + (A + B)); } } //実行Mainクラス public class Main { public static void main(String[] args) { Add add = new Add(); add.method1(); //”足し算をします"の表示 add.method3(); //定数の足し算の結果表示 } }
実行結果:
足し算をします 計算結果: 9
このサンプルコードでは、まずCalc1インターフェースを宣言しています。
文字列型とint型の定数を定義し、3種類のメソッドの型だけを宣言しています。これをAddクラスで実装しています。
Addクラス内ではCalc1インターフェースで宣言したメソッドの処理内容を記述しています。
実行(Main)クラスではAddクラスをインスタンス化し、Addクラスで記述したメソッドの処理が実行されています。
処理内容を変える方法
それでは次に、処理を変える必要が出てきた場合をみていきましょう。
これまでは足し算の処理でしたが、掛け算に変えてみます。
サンプルコードをみていきましょう。
//インターフェースの宣言 interface Calc1{ //メンバ変数(定数) public String STR = "足し算"; public int A = 3; public int B = 6; //メソッド(型のみ宣言) void method1(); void method2(String str); void method3(); } //インターフェースの実装 class Add implements Calc1{ // メソッドの実装 public void method1() { System.out.println(STR + "をします"); } public void method2(String str) { System.out.println(str + "をします"); } public void method3() { System.out.println("計算結果: " + (A + B)); } } // 処理内容の変更用のクラス class Multiply implements Calc1{ // メソッドの実装 public void method1() { System.out.println(STR + "をします"); } public void method2(String str) { System.out.println(str + "をします"); } public void method3() { System.out.println("計算結果: " + (A * B)); // 掛け算に変更 } } //実行Mainクラス public class Main { public static void main(String[] args) { Multiply mul = new Multiply(); mul.method2("掛け算"); //”掛け算をします"の表示 mul.method3(); //定数の足し算の結果表示 } }
実行結果:
掛け算をします 計算結果: 18
このサンプルコードでは、計算処理内容の変更のためにMultiplyクラスを追加し、Mainクラスの記述の一部を変更しています。このようにクラスの追加と実行処理の記述の一部を変更することで処理内容を変更することができます。
ここで、注意があります。
足し算から掛け算に変更したので、表示する文字列を”掛け算をします”に変更しました。
その際に
mul.STR = “掛け算”;
と記述したくなりますが、これは出来ません。
Calc1インターフェースで
public String STR
と定義していても、「public static final」が付いているものとみなされ、定数として扱われるからです。
注意しましょう!
この例では、AddクラスとMainクラスの記述されている場所が近いので、このような書き方をすると確かに”なぜ?”となるかもしれません。
しかし、例えばCalc1インターフェースとAddクラスがMainクラスとは別のファイルに記述されている場合はどうでしょうか?処理を変更したい場合は、Addクラスを見つけ出して書き直す必要がありますよね。
でもinterfaceを使えば、MultiplyクラスのようにMainクラスと同じファイル内に処理の変更を記述することができます。
探して書き換える手間が省けるのがメリットなのです。
処理が複雑になり記述量が多くなると、多数のファイルに分けて記述するという機会が増えます。
そんな場合はinterfaceでメソッドの型だけ宣言しておいて処理は別で記述する方が、後々の変更などが予想される場合には便利になってくるのです。
interfaceとdefaultの使い方
interfaceのメソッドに「default」句を使うと、処理内容を実装したメソッドを定義することができます。
詳しい解説についてはこちらを参照してくださいね。
interfaceとstaticメソッドの使い方
interfaceで定義する変数は「public static final」が付いているものとみなされ、定数として扱われるとお伝えしました。
それではinterfaceで定義するメソッドに「static」をつけるとどうなるのでしょうか?
メソッドに「static」句をつけると、インスタンスを生成せずにそのメソッドを使用することができます。
サンプルコードで確認していきましょう。
//インターフェースの宣言 interface Calc1{ //メンバ変数(定数) public String STR = "足し算"; public int A = 3; public int B = 6; //メソッド(型のみ宣言) public static void method1() { System.out.println(STR + "をします"); } public static void method2(String str) { System.out.println(str + "をします"); } public static void method3() { System.out.println("計算結果: " + (A + B)); } } //実行Mainクラス public class Main { public static void main(String[] args) { Calc1.method1(); //”足し算をします"の表示 Calc1.method3(); //定数の足し算の結果表示 } }
実行結果:
足し算をします 計算結果: 9
このサンプルコードでは、まずCalc1インターフェースを宣言しています。
文字列型とint型の定数を定義し、3種類のメソッド全てに「static」句を付け、さらに処理内容を定義しています。
実行(Main)クラスではインスタンスを生成せずに、Calc1インターフェースで記述したメソッドを呼び出し実行しています。
interfaceとabstract(抽象クラス)との違い
インターフェースの特徴は多重継承できることです。
多重継承とは1つのクラスが複数の親クラスを持つことを言います。多重継承をすることにより、1つのクラスは2つのクラスの性質を同時に受け継ぐ事になります。
同じように抽象クラスを使っても、別でメソッドの処理内容を決めることができます。
しかし、抽象クラスでは多重継承をすることができません。クラスは多重継承することができず、したがってクラスである抽象クラスも多重継承ができないのです。
それに対して、インターフェースはクラスではなく、多重継承が可能なのがインターフェースと抽象クラスの大きな違いになります。
インターフェースを使った多重継承の例をサンプルコードでみてみましょう。
//インターフェースの宣言 interface Add{ //メンバ変数(定数) public int A = 3; public int B = 6; //メソッド(型のみ宣言) void method(String str); void add(); } //インターフェースの宣言 interface Multiply{ //メンバ変数(定数) public int A = 4; public int B = 8; //メソッド(型のみ宣言) void method(String str); void mul(); } //インターフェースの実装 class Calc implements Add, Multiply{ public void method(String str) { // 文字列の表示 System.out.println(str + "をします"); } public void add() { // Addインターフェース内の足し算 System.out.println("計算結果: " + (Add.A + Add.B)); } public void mul() { // Multiplyインターフェース内の掛け算 System.out.println("計算結果: " + (Add.A * Add.B)); } } //実行Mainクラス public class Main { public static void main(String[] args) { Calc calc = new Calc(); calc.method("足し算"); calc.add(); calc.method("掛け算"); calc.mul(); } }
実行結果:
足し算をします 計算結果: 9 掛け算をします 計算結果: 18
このサンプルコードでは、AddインターフェースとMultiplyインターフェースを宣言しています。
AddインターフェースとMultiplyインターフェースの両方を実装するCalcクラスを定義しています。AddインターフェースとMultiplyインターフェースで、int型定数のA、Bとメソッドのmethodは同じ名称ですが、問題ありません。
ただしこの場合、int型定数のAおよびBを引数とすると、AddインターフェースとMultiplyインターフェースのどちらの定数を指定しているかあいまいなため、どちらか明示する必要があります。
ここではAddインターフェースのAおよびBを指定しています。
実行(Main)クラスではCalcクラスをインスタンス化し、それぞれのメソッドの処理を実行しています。
また、abstract(抽象クラス)の詳しい使い方についてはこちらを参考にしてくださいね!
interface(インタフェース)の使い方総まとめ
interface(インタフェース)のいろいろな使い方を次の記事にまとめているので、ぜひ確認してください!
まとめ
ここでは、interfaceについて説明してきましたがいかがだったでしょうか?
処理の内容を決めずに型だけ宣言して別で処理を決めるメリットや、複数のインターフェースのメソッドを1つのクラスにまとめることができるメリットを感じて頂けましたでしょうか?
“処理を書くのがプログラム”という思いがあるので慣れが必要かもしれませんが、そんな場合はこの記事を何度も参考にして下さいね!