Javaによるプログラミングに関する世界観2B(インターフェース)です。オブジェクト指向も参照のこと。
デザインパターンも参照のこと。
インターフェースは、違うクラスに同じ操作インターフェースを提供する技術。
キーワード | 説明 |
---|---|
interface | インターフェースを宣言する。 |
implements | インターフェースを実装したクラスの宣言をする。 |
Javaでは、継承するだけではなく、インターフェースを実装することで、「同じ操作形態を持った別のメソッド」を作ることができる。
インターフェースは、さまざまな種類の違うクラスに対して共通の「呼び出し規約」を持たせる。
インターフェースを各クラスで実装することで、それぞれ異なるクラスであっても同じインターフェースを実装した同様のクラスとしてさまざまなクラスを操作することができる。
たとえば、read()とwrite()を持つインターフェースは以下のように定義する。
interface ReaderAndWriter { void read(); void write(); }
これを以下のように実装する。
public class FileManager implements ReaderAndWriter { public void read() { ... } public void write() { ... } } public class NetworkIOManager implements ReaderAndWriter { public void read() { ... } public void write() { ... } }
そして以下のように利用する。
public class IO { public static void main(String[] args) { ReaderAndWriter manager; if (...) { manager = new FileManager(); } else if (...) { manager = new NetworkIOManager(); } manager.read(); manager.write(); } }
以下のように、インターフェースをメソッドの引数に用いれば、異なるクラスのオブジェクトを渡して、メソッドの中から操作できる。
public class IO2 { public static void operation(ReaderAndWriter manager) { manager.read(); manager.write(); } public static void main(String[] args) { FileManager fmanager = new FileManager(); NetworkIOManager nmanager = new NetworkIOManager(); operation(fmanager); operation(nmanager); } }
このように、ほかの言語でポリモーフィズムやダックタイピングを用いて行うことは、Javaでは継承やインターフェースを用いて行うことができる。
何のためにインターフェースを使うのか、それは異なるクラスを同じ操作体系で操作するためです。
たとえば、最初にread()やwrite()をメソッドに持つインターフェースを作っておけば、そのインターフェースを実装したクラスのオブジェクトは、どんなに派生し改良されても、同じ呼び出しメソッドから呼び出すことができます。
このため、たとえば、クラスのメンバ関数としてインスタンスを持っていた場合などに、「そのインスタンス変数にさまざまなクラス(共通のインターフェースを実装したクラス)を詰め込むことができる」のです。
つまり、クラスの中にキャッシュ管理を行う別のクラスのオブジェクトがあったとして、最初にread()やwrite()を実装しておけば、たとえばキャッシュに加えてプロキシ機能を実装したクラスであっても、インスタンスの中に入れることができます。そして、そのクラスはキャッシュ機能にプロキシ機能を加えることが、その呼び出し元のプログラムを変更することなく実現することができます。
同様に、掲示板とチャットのクラスがあったとして、それに発言する機能を付ける場合や、逆に掲示板やチャットの機能を埋め込んで使うWebサービスのような機能を作る時などに、応用が利くと思います。
インターフェースという言葉がしっくりこない場合は、CORBAのインターフェースのようなものだと考えると良いでしょう。
インターフェースを使うことで、「まだ書かれていない未知のプログラム」や、「違う場所で他人によって書かれたプログラム」に対して、プログラムの中であらかじめ対応することができる。簡単なプラグイン機構のようなものも応用として実現できる。
Javaのインターフェースの特徴として、多重継承(多重実装)できるということが言える。インターフェースを実装するクラスは、複数のインターフェースを同時に実装できる。また、インターフェースで定められているメソッドはすべて実装しなければならない。これらの点が抽象クラスと異なる。多重継承できないJavaであっても、C++の多重継承と同じようなことがインターフェースを用いて可能となる。
詳しくは以下の書籍が参考になります。
インターフェースとは、APIの呼び出し規約だけをすべて宣言した型のことであり、C/C++のヘッダファイルとよく似ていますが、実際にはヘッダファイルよりもより柔軟です。
Javaでは、ヘッダファイルを使わなくても、クラス定義だけでclassファイルのAPIを読み込むことができるため、ヘッダファイルに相当するものはありません。
Javaのインターフェースは、複数のクラスや型であっても、共通のAPIを持つインターフェースを元に実装して、共通の呼び出し規約を持って操作できます。
これは、たとえばメソッドの引数にインターフェースの型を渡したり、あるいはメンバとしてインターフェースの型を持つことができるということを意味します。
インターフェースは複数の型で共通のAPIを持つことができるため、この特徴は、「単なる特定のクラスではなく、より広い意味で分類されたクラスの種類を型として指定できる」ということを意味しています。
なので、インターフェースを使うと、さまざまな場合やシチュエーションに幅広く対応することができ、また後々改良したり機能を追加したりする「拡張性」が高くなります。
ひとつのクラスだけダイレクトに対応するのではなく、複数の「同じ種類のクラス」は同等に扱うことができる、ということが、Javaのインターフェースの優位性であると言えます。
同じことは継承でもできますが、インターフェースは多重継承ができ、また親クラスの異なるまったく関係のないクラスについても、同じAPIを持ったクラスであるとして、共通のインターフェースを実装して扱うことができます。
継承が「ツリー構造のサブツリーが同じAPIとして扱える」ということを意味するなら、インターフェースは「まったく異なる場所にあるノードであっても同じAPIとして扱える」ということを意味します。
また、C++で言えば、テンプレートによるダックタイピングはインターフェースとよく似ているところがあります。インターフェースの実装という方法ではなく、パラメータとして型を指定することで、さまざまな型に対して柔軟に型をその時作ることができるのが、テンプレートの良さです。
また、C++には多重継承も存在するので、C++ではJavaと同じインターフェースを使うことはありません。C++では通常のクラスとしてJavaのインターフェースに相当する「インターフェース専門のクラス」を定義し、通常のクラスと同じように継承することができます。
Javaのインターフェースを使うことで、異なるものを同じものとして扱うことができます。
たとえば、ハードウェアの場合、個々のデバイスの実装は異なりますが、デバイスドライバのレベルで個々の詳細を実装し、OSのレベルでそのデバイスを扱うためのインターフェースを共通にし、カプセル化することで、すべてのハードウェアデバイスをどのアプリケーションからでも、デバイスドライバとOSを仲介して使うことができます。
同様のことを、Javaのインターフェースを使うことで、ソフトウェアレベルで行うことができます。
たとえば、統合開発環境のEclipseなどは、基本的な開発環境にプラグインを追加する形で機能を拡張することができます。このような場合、プラグインそれぞれの具体的な機能は違いますが、Eclipseからプラグインを操作するためのインターフェースを共通化し、すべてのプラグインで同じインターフェースから操作できます。
ほかにも、ウィジェットツールキットなどでも、どのウィジェットであっても同じインターフェースから操作できるようにすると、ボタンであってもメニューであってもテキストボックスであっても、あるいはユーザー定義の独自のウィジェットであっても同じように利用できます。
その他の例として、マルチスレッド環境を実現する場合、プログラマが独自に個々のスレッドを実装し、その実装したスレッドを、スレッドを使って様々な機能を提供するさまざまなクラスに渡すことで、スレッドの機能をさまざまなところで同じインターフェースから利用することができます。
あるいは、ファイルシステムを操作する際に、そのファイルシステムがどのような具体的な形式でフォーマットされていても、ローカルに存在せずネットワーク上に存在するとしても、それらを同じものとして操作することができます。
このようなJavaのインターフェースを使うことで、プログラムの開発と利用がとても便利になります。同じインターフェースを実装したクラスが同じように操作できるというだけで、とてもプログラムの開発がしやすくなるのです。Javaのインターフェースは、OSや仮想化のような仕組みを、オブジェクト指向のプログラミング言語として実現したものであると言えます。
2023.05.06
インターフェースを参照のこと。