例で説明されたJavaインターフェイス

インターフェイス

Javaのインターフェイスはクラスに少し似ていますが、大きな違いがあります。メソッドシグネチャ、フィールド、およびデフォルトメソッドのみを持つinterfaceことができます。Java 8以降、デフォルトのメソッドを作成することもできます。次のブロックでは、インターフェースの例を見ることができます。

public interface Vehicle { public String licensePlate = ""; public float maxVel public void start(); public void stop(); default void blowHorn(){ System.out.println("Blowing horn"); } }

上記のインターフェースには、2つのフィールド、2つのメソッド、およびデフォルトのメソッドが含まれています。単独ではあまり役に立ちませんが、通常はクラスと一緒に使用されます。どうやって?簡単です、あなたはいくつかのクラスを確認する必要がありますimplements

public class Car implements Vehicle { public void start() { System.out.println("starting engine..."); } public void stop() { System.out.println("stopping engine..."); } }

ここで、基本ルールがあります。クラスは、インターフェイスのすべてのメソッドを実装する必要があります。メソッドには、インターフェースで説明されているものとまったく同じシグニチャー(名前、パラメーター、および例外)が必要です。ただし、クラスフィールドを宣言する必要はなく、メソッドのみを宣言する必要があります。

インターフェイスのインスタンス

implements任意のインターフェースであるJavaクラスを作成すると、オブジェクトインスタンスをインターフェースのインスタンスとして参照できます。この概念は、継承のインスタンス化の概念に似ています。

// following our previous example Vehicle tesla = new Car(); tesla.start(); // starting engine ...

インターフェイスにコンストラクタメソッドを含めることはできません。したがって、インターフェイス自体のインスタンスを作成することはできません。それを参照するには、インターフェイスを実装するクラスのインスタンスを作成する必要があります。

インターフェースは、空白の契約書またはテンプレートと考えてください。

この機能で何ができますか?ポリモーフィズム!オブジェクトインスタンスを参照するために使用できるのはインターフェイスのみです。

class Truck implements Vehicle { public void start() { System.out.println("starting truck engine..."); } public void stop() { System.out.println("stopping truck engine..."); } } class Starter { // static method, can be called without instantiating the class public static void startEngine(Vehicle vehicle) { vehicle.start(); } } Vehicle tesla = new Car(); Vehicle tata = new Truck(); Starter.startEngine(tesla); // starting engine ... Starter.startEngine(tata); // starting truck engine ...

しかし、複数のインターフェースはどうですか?

はい、1つのクラスに複数のインターフェースを実装できます。クラス内の継承では、1つのクラスのみを継承するように制限されていましたが、ここでは任意の数のインターフェイスを拡張できます。ただし、すべてのインターフェイスのすべてのメソッドを実装することを忘れないでください。そうしないと、コンパイルが失敗します。

public interface GPS { public void getCoordinates(); } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } }

インターフェースのいくつかの機能

  • インターフェイス内に変数を配置できますが、クラスが同じ変数を持つようにバインドされていないため、賢明な決定にはなりません。つまり、変数の配置は避けてください。
  • publicキーワードを省略した場合でも、インターフェイス内のすべての変数とメソッドはパブリックです。
  • インターフェイスは、特定のメソッドの実装を指定できません。それを行うのはクラス次第です。最近の例外がありますが(以下を参照)。
  • クラスが複数のインターフェイスを実装している場合、メソッドシグネチャが重複する可能性はほとんどありません。Javaではまったく同じ署名の複数のメソッドが許可されていないため、これにより問題が発生する可能性があります。詳細については、この質問を参照してください。

インターフェイスのデフォルトメソッド

Java 8以前は、特定のメソッドを実装するようにインターフェイスに指示する方法がありませんでした。これにより、インターフェイス定義が突然変更された場合、多くの混乱とコードの中断が発生します。

インターフェイスを含むオープンソースライブラリを作成したとします。たとえば、クライアント、つまり世界中のほぼすべての開発者がこれを頻繁に使用していて、満足しているとします。これで、新しい機能をサポートするために、インターフェイスに新しいメソッド定義を追加してライブラリをアップグレードする必要がありました。ただし、そのインターフェイスを実装するすべてのクラスを変更する必要があるため、すべてのビルドが破損ます。なんて大惨事でしょう。

ありがたいことに、Java8defaultはインターフェイスのメソッドを提供するようになりました。defaultこの方法は、できる独自の実装が含まれている直接インタフェース内!したがって、クラスがデフォルトのメソッドを実装していない場合、コンパイラはインターフェイス内で説明されている実装を採用します。いいですね。したがって、ライブラリでは、何かを壊すことを恐れることなく、インターフェイスにデフォルトのメソッドをいくつでも追加できます。

public interface GPS { public void getCoordinates(); default public void getRoughCoordinates() { // implementation to return coordinates from rough sources // such as wifi & mobile System.out.println("Fetching rough coordinates..."); } } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } // no implementation of getRoughCoordinates() } Smartphone motoG = new Smartphone(); motog.getRoughCoordinates(); // Fetching rough coordinates...

しかし、2つのインターフェイスが同じメソッドシグネチャを持っている場合はどうなりますか?

素晴らしい質問です。その場合、クラスで実装を提供しないと、貧弱なコンパイラは混乱し、単に失敗します!クラス内にもデフォルトのメソッド実装を提供する必要があります。super好きな実装を呼び出すために使用する気の利いた方法もあります。

public interface Radio { // public void startRadio(); // public void stopRadio(); default public void next() { System.out.println("Next from Radio"); } } public interface MusicPlayer { // public void start(); // public void pause(); // public void stop(); default public void next() { System.out.println("Next from MusicPlayer"); } } public class Smartphone implements Radio, MusicPlayer { public void next() { // Suppose you want to call MusicPlayer next MusicPlayer.super.next(); } } Smartphone motoG = new Smartphone(); motoG.next(); // Next from MusicPlayer

インターフェイスの静的メソッド

また、Java 8の新機能として、静的メソッドをインターフェースに追加する機能があります。インターフェイスの静的メソッドは、具象クラスの静的メソッドとほとんど同じです。唯一の大きな違いは、staticメソッドがインターフェイスを実装するクラスに継承されないことです。これは、インターフェースを実装するクラスではなく、静的メソッドを呼び出すときにインターフェースが参照されることを意味します。

interface MusicPlayer { public static void commercial(String sponsor) { System.out.println("Now for a message brought to you by " + sponsor); } public void play(); } class Smartphone implements MusicPlayer { public void play() { System.out.println("Playing from smartphone"); } } class Main { public static void main(String[] args) { Smartphone motoG = new Smartphone(); MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class // motoG.commercial("Motorola"); // This would cause a compilation error } }

インターフェイスの継承

Javaでは、ご想像のとおり、次のキーワードを使用して、インターフェイスが別のインターフェイスを継承することもできますextends

public interface Player { public void start(); public void pause(); public void stop(); } public interface MusicPlayer extends Player { default public void next() { System.out.println("Next from MusicPlayer"); } }

ことは、クラスが実装するMusicPlayerインタフェースを実装する必要があり、すべての方法MusicPlayerと同様にしPlayer

public class SmartPhone implements MusicPlayer { public void start() { System.out.println("start"); } public void stop() { System.out.println("stop"); } public void pause() { System.out.println("pause"); } }

これで、Javaインターフェイスを十分に理解できました。抽象クラスについて学び、Javaがコントラクトを定義するさらに別の方法をどのように提供するかを確認してください。