Javaにおけるインターフェース
Javaのインタフェースは、コアの概念の1つです。Javaのインタフェースは、Javaプログラミング言語の中核的な部分であり、JDKだけでなくJavaの設計パターンでも広く使用されています。多くのフレームワークはJavaのインタフェースを大量に使用しています。
Javaでのインターフェース
Javaのインターフェースは、抽象化を実現するための手段を提供します。Javaのインターフェースは、サブクラスが実装する契約を定義するためにも使用されます。例えば、複数の図形からなる描画を作成したいとします。ここでは、Shapeというインターフェースを作成し、異なる種類のShapeオブジェクトが実装するすべてのメソッドを定義します。単純化のために、描画するためのdraw()メソッドと図形の面積を返すgetArea()メソッドのみを保持することができます。
Java インターフェースの例
上記の要件に基づいて、私たちのShapeインターフェースは以下のようになります。Shape.java
package com.scdev.design;
public interface Shape {
//implicitly public, static and final
public String LABLE="Shape";
//interface methods are implicitly abstract and public
void draw();
double getArea();
}
Javaにおけるインターフェースに関する重要なポイント
-
- インターフェースは、Javaでインターフェースを作成するために使用されるコードです。
-
- Javaでは、インターフェースをインスタンス化することはできません。
-
- インターフェースは完全な抽象化を提供します。前の投稿では、抽象クラスを使用して抽象化を提供しましたが、抽象クラスにはメソッドの実装ができますが、インターフェースにはできません。
-
- インターフェースにはコンストラクタを持つことはできません。インターフェースをインスタンス化することはできないため、インターフェースには本体を持つメソッドもありません。
-
- デフォルトでは、インターフェースの属性はpublic、static、finalです。したがって、属性にアクセス修飾子を提供する必要はありませんが、提供した場合でも、コンパイラはエラーを報告しません。
-
- デフォルトでは、インターフェースのメソッドは暗黙的に抽象でpublicです。これは完全に理解できます。メソッドには本体がないため、サブクラスがメソッドの実装を提供できるようになっています。
-
- インターフェースはどのクラスも継承できませんが、他のインターフェースを継承することは可能です。public interface Shape extends Cloneable{}は、別のインターフェースを継承するインターフェースの例です。実際、Javaではインターフェースで複数の継承が可能です。
-
- implementsキーワードは、クラスがインターフェースを実装するために使用されます。
-
- インターフェースを実装するクラスは、抽象クラスでない限り、すべてのメソッドの実装を提供する必要があります。上記のインターフェースを次のように抽象クラスで実装することはできます: ShapeAbs.java
-
- パッケージcom.scdev.design;
public abstract class ShapeAbs implements Shape {
@Override
public double getArea() {
return 0;
}
}
プログラムを実装に関連付けて書くようにすると、将来的にもっと良い実装が現れた場合に容易に切り替えることができるため、常にインターフェースの観点でプログラムを作成するべきです。
Javaのインターフェースの実装例
今度は、JavaでShapeインターフェースの実装をいくつか見てみましょう。Circle.java
package com.scdev.design;
public class Circle implements Shape {
private double radius;
public Circle(double r){
this.radius = r;
}
@Override
public void draw() {
System.out.println("Drawing Circle");
}
@Override
public double getArea(){
return Math.PI*this.radius*this.radius;
}
public double getRadius(){
return this.radius;
}
}
円クラスがインターフェースで定義されたすべてのメソッドを実装しており、さらにgetRadius()のような独自のメソッドも持っていることに注目してください。インターフェースの実装は複数のタイプのコンストラクタを持つことができます。では、Shapeインターフェースのもう一つの実装であるRectangle.javaを見てみましょう。
package com.scdev.design;
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double w, double h){
this.width=w;
this.height=h;
}
@Override
public void draw() {
System.out.println("Drawing Rectangle");
}
@Override
public double getArea() {
return this.height*this.width;
}
}
オーバーライドの注釈の使用に注意し、Javaの注釈について学び、Javaでメソッドをオーバーライドする際には常にオーバーライドの注釈を使用するべきである理由について知ってください。以下は、インターフェースを用いてコーディングする方法を示したテストプログラムの例です。ShapeTest.java
package com.scdev.design;
public class ShapeTest {
public static void main(String[] args) {
//programming for interfaces not implementation
Shape shape = new Circle(10);
shape.draw();
System.out.println("Area="+shape.getArea());
//switching from one implementation to another easily
shape=new Rectangle(10,10);
shape.draw();
System.out.println("Area="+shape.getArea());
}
}
上記のJavaインターフェイスの例プログラムの出力は次のとおりです。
Drawing Circle
Area=314.1592653589793
Drawing Rectangle
Area=100.0
Java インターフェースの利点
-
- インターフェースは、すべての実装クラスに対する契約を提供するため、インターフェースの用語でコーディングすることは良いです。なぜなら、実装クラスは私たちが使用しているメソッドを削除することができないからです。
-
- インターフェースは、タイプを定義し、コード内のトップレベルの階層を作成するための起点として役立ちます。
- Javaのクラスは複数のインターフェースを実装することができるため、ほとんどの場合はスーパークラスとしてインターフェースを使用することがより良いです。
Javaインターフェースのデメリット
インタフェースは多くの利点を提供しますが、いくつかの欠点もあります。
-
- 私たちはプロジェクトの設計時に非常に注意してインターフェースメソッドを選択する必要があります。なぜなら、後からインターフェースからメソッドを追加または削除することはできず、その結果、すべての実装クラスでコンパイルエラーが発生するからです。これにより、私たちのコードではベースインターフェースを拡張するような多くのインターフェースが必要になり、メンテナンスが難しくなります。
実装クラスに独自のメソッドがある場合、これらのメソッドを直接コードで使用することはできません。なぜなら、オブジェクトの型はそのようなメソッドを持っていないインターフェースであるからです。例えば、上記のコードでは、shape.getRadius()の部分でコンパイルエラーが発生します。これを解決するために、型キャストを使用して次のようにメソッドを使用することができます:
Circle c = (Circle) shape;
c.getRadius();
ただし、クラスの型キャストには欠点もあります。
これが私がJavaでのインターフェースについて持っているものです。Javaのインターフェースをよく使用するため、その特徴を理解する必要があります。システムの設計においてインターフェースを使用し、インターフェースを実装するクライアントとサブクラスとの契約として使用してください。追記:Java 8では、デフォルトメソッドと静的メソッドの実装を導入することで、インターフェースの定義が変わりました。詳細については、Java 8のインターフェースをご覧ください。